并查集+拓扑排序 赛码 1009 Exploration

时间:2023-03-10 04:08:54
并查集+拓扑排序 赛码 1009 Exploration

题目传送门

 /*
题意:无向图和有向图的混合图判环; 官方题解:首先对于所有的无向边,我们使用并查集将两边的点并起来,若一条边未合并之前,
两端的点已经处于同一个集合了,那么说明必定存在可行的环(因为这两个点处于同一个并查集集合中,那么它们之间至少存在一条路径)
如果上一步没有判断出环,那么仅靠无向边是找不到环的
考虑到,处于同一个并查集集合中的点之间必定存在一条路径互达,因此将一个集合的点合并之后,
原问题等价于在新生成的有向图中是否有环
我们知道,有向无环图必定存在拓扑序,因此只需使用拓扑排序判定即可
时间复杂度O(N+M1+M2) 并查集+拓扑排序:并查集来判断无向图,拓扑排序判断有向图 另外:用读入外挂时间比scanf ()多,不清楚...
Accepted 5222 5007MS 45124K 2158 B G++ BH //scanf ()
Accepted 5222 7581MS 45116K 2158 B G++ BH //read ()
*/
#include <cstdio>
#include <cmath>
#include <cstring>
#include <string>
#include <iostream>
#include <algorithm>
#include <queue>
#include <vector>
#pragma comment(linker, "/STACK:102400000,102400000")
using namespace std; const int MAXN = 1e6 + ;
const int INF = 0x3f3f3f3f;
int ans[MAXN], in[MAXN];
int rt[MAXN];
vector<int> G[MAXN];
int n, m1, m2; inline int read(void)
{
int x = , f = ; char ch = getchar ();
while (ch < '' || ch > '') {if (ch == '-') f = -; ch = getchar ();}
while (ch >= '' && ch <= '') {x = x * + ch - ''; ch = getchar ();}
return x * f;
} bool TopoSort(void)
{
memset (in, , sizeof (in));
for (int i=; i<=n; ++i)
for (int j=; j<G[i].size (); ++j) in[G[i][j]]++; queue<int> Q; int cnt = ;
for (int i=; i<=n; ++i) {if (!in[i]) Q.push (i);} while (!Q.empty ())
{
int u = Q.front (); Q.pop ();
ans[++cnt] = u;
for (int j=; j<G[u].size (); ++j)
{
int v = G[u][j];
in[v]--;
if (!in[v]) Q.push (v);
}
} if (cnt == n) return false;
else return true;
} int Find(int x)
{
return (rt[x] == x) ? rt[x] : rt[x] = Find (rt[x]);
} void Union(int x, int y)
{
x = Find (x); y = Find (y);
if (x < y) rt[x] = y;
else rt[y] = x;
} bool same(int x, int y)
{
return (Find (x) == Find (y)) ? true : false;
} int main(void) //赛码 1009 Exploration
{
//freopen ("I.in", "r", stdin); int t;
scanf ("%d", &t);
while (t--)
{
scanf ("%d%d%d", &n, &m1, &m2); for (int i=; i<=n; ++i) rt[i] = i;
for (int i=; i<=n; ++i) G[i].clear (); bool ok = false; int u, v;
for (int i=; i<=m1; ++i)
{
scanf ("%d%d", &u, &v);
//u = read (); v = read ();
//G[u].push_back (v);
if (same (u, v) == true) ok = true;
else Union (u, v);
}
for (int i=; i<=m2; ++i)
{
int u, v;
scanf ("%d%d", &u, &v);
//u = read (); v = read ();
if (same (u, v) == true) ok = true;
if (ok) continue;
G[u].push_back (v);
} if (ok) {puts ("YES"); continue;}
if (TopoSort () == true) puts ("YES");
else puts ("NO");
} return ;
}