Codeforces Round #594 (Div. 1) D. Catowice City 图论
D. Catowice City
In the Catowice city next weekend the cat contest will be held. However, the jury members and the contestants haven't been selected yet. There are 𝑛 residents and 𝑛 cats in the Catowice, and each resident has exactly one cat living in his house. The residents and cats are numbered with integers from 1 to 𝑛, where the 𝑖-th cat is living in the house of 𝑖-th resident.
Each Catowice resident is in friendship with several cats, including the one living in his house. In order to conduct a contest, at least one jury member is needed and at least one cat contestant is needed. Of course, every jury member should know none of the contestants. For the contest to be successful, it's also needed that the number of jury members plus the number of contestants is equal to 𝑛.
Please help Catowice residents to select the jury and the contestants for the upcoming competition, or determine that it's impossible to do.
Input
The first line contains an integer 𝑡 (1≤𝑡≤100000), the number of test cases. Then description of 𝑡 test cases follow, where each description is as follows:
The first line contains integers 𝑛 and 𝑚 (1≤𝑛≤𝑚≤106), the number of Catowice residents and the number of friendship pairs between residents and cats.
Each of the next 𝑚 lines contains integers 𝑎𝑖 and 𝑏𝑖 (1≤𝑎𝑖,𝑏𝑖≤𝑛), denoting that 𝑎𝑖-th resident is acquaintances with 𝑏𝑖-th cat. It's guaranteed that each pair of some resident and some cat is listed at most once.
It's guaranteed, that for every 𝑖 there exists a pair between 𝑖-th resident and 𝑖-th cat.
Different test cases are separated with an empty line.
It's guaranteed, that the sum of 𝑛 over all test cases is at most 106 and that the sum of 𝑚 over all test cases is at most 106.
Output
For every test case print:
"No", if it's impossible to select the jury and contestants.
Otherwise print "Yes".
In the second line print two integers 𝑗 and 𝑝 (1≤𝑗, 1≤𝑝, 𝑗+𝑝=𝑛) — the number of jury members and the number of contest participants.
In the third line print 𝑗 distinct integers from 1 to 𝑛, the indices of the residents forming a jury.
In the fourth line print 𝑝 distinct integers from 1 to 𝑛, the indices of the cats, which will participate in the contest.
In case there are several correct answers, print any of them.
Example
input
4
3 4
1 1
2 2
3 3
1 3
3 7
1 1
1 2
1 3
2 2
3 1
3 2
3 3
1 1
1 1
2 4
1 1
1 2
2 1
2 2
output
Yes
2 1
1 3
2
Yes
1 2
2
1 3
No
No
Note
In the first test case, we can select the first and the third resident as a jury. Both of them are not acquaintances with a second cat, so we can select it as a contestant.
In the second test case, we can select the second resident as a jury. He is not an acquaintances with a first and a third cat, so they can be selected as contestants.
In the third test case, the only resident is acquaintances with the only cat, so they can't be in the contest together. So it's not possible to make a contest with at least one jury and at least one cat.
In the fourth test case, each resident is acquaintances with every cat, so it's again not possible to make a contest with at least one jury and at least one cat.
题意
有n个人,有n只猫;有m个关系,每个关系用(x,y)表示,表示为第x个人认识第y只猫。现在小镇要举行比赛,现在让你选出猫和人参加比赛,一共要选择n个出来,但需要保证至少一个人和一只猫,且人和猫都不认识。这道题保证第i个人认识第i只猫。
题解
我们依次了解以下的知识点:
-
因为第i个人知道第j只猫,所以选了第i个人就不会选第i只猫;选了第i只猫就不会选第i个人。由于要选n个,所以要么选了第i个人,要么就必须选择第i只猫。
-
如果选了第i个人,第i个人认识第j只猫,所以第j只猫不能选,所以第j个人就必须选。翻译一下,我们以(i,j)建边,表示选了i就必须选择j,然后如果存在联通块,就表示这个联通块的东西都必须选。
所以这道题就是判断否存在一个大小小于n的联通块存在即可。枚举第一个人选择猫,还是选择人即可。
代码
#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e6+7;
int t,n,m;
vector<int> E[2][maxn];
int vis[2][maxn],cnt=0;
void dfs1(int x,int z){
vis[z][x]=1;
cnt++;
for(int i=0;i<E[z][x].size();i++){
int v=E[z][x][i];
if(vis[z][v])continue;
dfs1(v,z);
}
}
void clear(){
for(int i=1;i<=n;i++){
vis[0][i]=vis[1][i]=0;
E[0][i].clear();
E[1][i].clear();
}
}
void solve(){
scanf("%d%d",&n,&m);
clear();
for(int i=0;i<m;i++){
int x,y;
scanf("%d%d",&x,&y);
E[0][x].push_back(y);
E[1][y].push_back(x);
}
for(int z=0;z<2;z++){
cnt=0;
dfs1(1,z);
if(cnt<n){
puts("Yes");
if(z==0){
cout<<cnt<<" "<<n-cnt<<endl;
} else {
cout<<n-cnt<<" "<<cnt<<endl;
}
for(int i=1;i<=n;i++){
if(vis[z][i]==1-z)cout<<i<<" ";
}
cout<<endl;
for(int i=1;i<=n;i++){
if(vis[z][i]==z)cout<<i<<" ";
}
cout<<endl;
return;
}
}
puts("No");
}
int main(){
scanf("%d",&t);
while(t--)solve();
return 0;
}