Hint
If you need a larger stack size, please use #pragma comment(linker, "/STACK:102400000,102400000") and submit your solution using C++.
大意:判一个图是否有环,对于无向图来说用并查集来判,对于有向图来说用topo来判,如果这两个点有相同的父亲结点的话就说明是一个环,否则就把他们join一起,topo用邻接表实现比模拟链表方便~~复习了并查集的三个函数
#include<cstdio>
#include<cstring>
#include<vector>
#include<algorithm>
#include<queue>
using namespace std;
const int MAX = 1e6 + 10;
int ans[MAX],in[MAX];
int n,m1,m2;
int p[MAX];
vector<int> G[MAX];
int find(int x)
{
return (x == p[x])? x:p[x] = find(p[x]);
}
void join(int x,int y)
{
int fx = find(x);
int fy = find(y);
if(fx != fy)
p[fx] = fy;
}
int judge(int x,int y)
{
return find(x) == find(y) ? 1 :0;
}
int topo()
{
memset(in,0,sizeof(in));
for(int i = 1; i <= n ; i++)
for(int j = 0 ; j < G[i].size();j++)
in[G[i][j]]++;
queue<int> q;
while(!q.empty())
q.pop();
int cnt = 1;
for(int i = 1; i <= n ; i++)
if(!in[i])
q.push(i);
while(!q.empty()){
int u = q.front();
q.pop();
ans[cnt++] = u;
for(int i = 0; i < G[u].size();i++){
int v = G[u][i];
in[v]--;
if(!in[v])
q.push(v);
}
}
if(cnt == n ) return 0;
else return 1;
}
int main()
{
int T;
scanf("%d",&T);
while(T--){
scanf("%d%d%d",&n,&m1,&m2);
for(int i = 1; i <= n ; i++)
p[i] = i;
for(int i = 1; i <= n ; i++)
G[i].clear();
int flag = 0;
int u,v;
for(int i = 1; i <= m1 ; i++){
scanf("%d%d",&u,&v);
if(judge(u,v) == 1) {
flag = 1;
break;
}
else join(u,v);
}
for(int i = 1; i <= m2; i++){
scanf("%d%d",&u,&v);
if(judge(u,v) == 1){
flag = 1;
break;
}
if(flag == 1)
break;
G[u].push_back(v);
}
if(flag == 1) {printf("YES\n");continue;}
if(topo() == 1) {
printf("NO\n");
}
else printf("YES\n");
}
return 0;
}