wxyww

一个OIER

我们要有最朴素的生活,与最遥远的梦想。即使明日天寒地冻,路远马亡。


CF1248F Catowice City

题目链接

problem

有$n$个人,每个人家有一只猫。每个人都认识一些猫(其中肯定包括自己家的猫)。选出$j$个人和$k$只猫$j,k\ge 1$。使得$j+k=n$且选出的人和猫都互不认识。

solution

一个显然但是重要的推论是:

每个人家都必须去一个人或者一只猫。

这样我们只需要枚举第一个人家去的是人还是猫,就可以根据他们之间的关系推出其他的人家是人还是猫。当无论第一家选择人还是选择猫,都会导致去$n$只猫或者$n$个人时无解。

code

#include<cstdio>
#include<queue>
#include<vector>
#include<algorithm>
#include<iostream>
#include<cstring>
#include<ctime>
using namespace std;
typedef long long ll;
const int N = 1000100;
ll read() {
	ll x = 0,f = 1;char c = getchar();
	while(c < '0' || c > '9') {
		if(c == '-') f = -1;c = getchar();
	}
	while(c >= '0' && c <= '9') {
		x = x * 10 + c - '0';
		c = getchar();
	}
	return x * f;
}
vector<int>e1[N],e2[N];
int vis[N],cnt;
void dfs(int u) {
	vis[u] = 1;cnt++;
	for(vector<int>::iterator it = e1[u].begin();it != e1[u].end();++it) {
		if(vis[*it]) continue;
		dfs(*it);
	}
}
void dfs2(int u) {
	vis[u] = 1;cnt++;
	for(vector<int>::iterator it = e2[u].begin();it != e2[u].end();++it) {
		if(vis[*it]) continue;
		dfs2(*it);
	}
}
int main() {
	int T = read();
	while(T--) {
		int n = read(),m = read();
		cnt = 0;
		for(int i = 1;i <= n;++i) vis[i] = 0;
		for(int i = 1;i <= n;++i) e1[i].clear(),e2[i].clear();
		for(int i = 1;i <= m;++i) {
			int u = read(),v = read();
			e1[u].push_back(v);e2[v].push_back(u);
		}
		dfs(1);
		int bz = 1;
		if(cnt == n) {
			cnt = 0;
			for(int i = 1;i <= n;++i) vis[i] = 0;
			dfs2(1);
			if(cnt == n) {puts("No");continue;}
			cnt = n - cnt;
			bz = 0;
		}
		puts("Yes");
		printf("%d %d\n",cnt,n - cnt);
		for(int i = 1;i <= n;++i) {
			if(vis[i] == bz) printf("%d ",i);
		}
		puts("");
		for(int i = 1;i <= n;++i) {
			if(vis[i] != bz) printf("%d ",i);
		}
		puts("");
	}
	return 0;
}
最近的文章

用容斥解决错排问题

错排问题简单来说,错排问题就是问有多少个长度为$n$的排列$p$,使得对于所有的$i\in [1,n]$都有$i \neq p_i$。递推式错排的一个递推式就是$f(n)=n(f(n-1)+f(n-2))$这个递推式复杂度显然是线性的。关于这个递推式的推导请自行百度。这里不再赘述。容斥法解错排问题第一次看到错排问题的时候,并没有推导出上面的递推式。而是用了一种容斥的方法。自认为更加简单易懂吧。既然是每个数字都不能放在对应的位置。那么按照容斥的一般套路,我们强制有$i$个数字放在了对应位置。...…

数学,错排继续阅读
更早的文章

CF1248E Queue in the Train

题目链接problem火车上的一列人要去排队接水。每个人都会在某个特定的时刻口渴。口渴之后他要去排队接水,如果他前面的座位有人已经在排队或者正在接水,那么他就不会去排队。否则他就会去排队。每个人接水都为一个相同的时间P。问每个人接完水的时间。solution其实模拟即可。注意题目的要求。如果一个人口渴的时候已经在排队的人中最靠前的位置也在他后面,那么他就要去排队。否则就把他扔到一个按位置从小到大排序的优先队列里面。然后模拟就行了。code#include<cstdio>#inc...…

模拟,堆继续阅读