题意:给你一个图 图上边有的无向有的有向 问你这个图是否有环
思路:对于所有相连的无向边 我们可以用并查集将他们分为一个集合 如果一条无向边的两个点属于同一集合 则说明有一个无向环 如果不存在无向环 就将所有无向边缩成一个点与有向边建图 如果这个图存在点数大于一的强连通分量 则存在一个有向环 我按照这个思路交上去之后wa了 然后发现一种特殊情况:两个节点间连着一条无向边和一条有向边 按照上面的思路 将会建一个自己指向自己的有向图 而这个图不存在点数大于一的强连通分量 但事实上这个图是个有环图 解决方法就是 在建立有向图的过程中判断一条边的两个结点是否相同即可
#include <cstdio>
#include <cstring>
#include <algorithm>
#pragma comment(linker, "/STACK:102400000,102400000")
using namespace std ;
#define REP( i, a, b ) for( int i = a; i < b; i++ )
#define CLR( a , x ) memset( a , x , sizeof a )
const int maxn = 1000000 + 10;
const int maxe = 1000000 + 10;
struct Edge{
int v , next;
Edge (int v = 0, int next = 0) : v(v), next(next) {}
};
struct SCC{
int Head[maxn], cntE;
int dfn[maxn], low[maxn], dfs_clock;
int scc[maxn], scc_cnt;
int Stack[maxn], top;
bool ins[maxn];
Edge edge[maxe];
void init(){
top = 0;
cntE = 0;
scc_cnt = 0;
dfs_clock = 0;
CLR(ins, 0);
CLR(dfn, 0);
CLR(Head, -1);
}
void add(int u, int v){
edge[cntE] = Edge( v, Head[u]);
Head[u] = cntE++;
}
void Tarjan(int u){
dfn[u] = low[u] = ++dfs_clock;
Stack[top++] = u;
ins[u] = 1;
for (int i = Head[u] ; ~i ; i = edge[i].next){
int v = edge[i].v;
if (!dfn[v]){
Tarjan (v) ;
low[u] = min(low[u], low[v]) ;
}
else if (ins[v])
low[u] = min (low[u], dfn[v]) ;
}
if (low[u] == dfn[u]){
++scc_cnt;
while ( 1 ){
int v = Stack[--top];
ins[v] = 0;
scc[v] = scc_cnt;
if (v == u)
break;
}
}
}
void find_scc(int n){
REP(i, 0, n) if(!dfn[i]) Tarjan (i) ;
}
}scc;
int path[maxn], vis[maxn];
int find_set(int x){ return path[x] == x ? x : path[x] = find_set (path[x]); }
void solve(){
int n, m1, m2;
int flag = 0;
scanf("%d%d%d", &n, &m1, &m2);
REP(i, 0, n) path[i] = i;
scc.init();
CLR(vis, 0);
REP(i, 0, m1){
int u, v;
scanf("%d%d", &u, &v);
--u; --v;
int x = find_set(u);
int y = find_set(v);
if(x != y) path[x] = y;
else flag = 1;
}
REP(i, 0, m2){
int u, v;
scanf("%d%d", &u, &v);
--u; --v;
int x = find_set(u);
int y = find_set(v);
if(x == y) flag = 1;
scc.add(x, y);
}
if(flag){
printf("YES\n");
return;
}
scc.find_scc(n);
REP(i, 0, n){
if(++vis[scc.scc[i]] > 1){
flag = 1;
break;
}
}
if(flag) printf("YES\n");
else printf("NO\n");
}
int main()
{
int T;
scanf("%d", &T);
while(T--) solve();
return 0;
}
/*
1
2 1 1
1 2
1 2
*/