題目鏈接
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;
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/95064.html
標籤:C++
上一篇:順序堆疊的表示與實作
下一篇:執行緒通訊wait¬ify
