拓扑排序的性质
拓扑排序的性质:排完序之后,若最后tt存的不是n-1,即未把所有点都打入q,q[i]存的是拓扑排序后第i个点是多少,可以用s[q[i]]=i,方便取用,如果全部入q,不论是不是一个连通块,只要无环,就会全部入q,之后,按照先后顺序排点即可
给定一个由 nn 个点和 mm 条边构成的图。
不保证给定的图是连通的。
图中的一部分边的方向已经确定,你不能改变它们的方向。
剩下的边还未确定方向,你需要为每一条还未确定方向的边指定方向。
你需要保证在确定所有边的方向后,生成的图是一个有向无环图(即所有边都是有向的且没有有向环的图)。
输入格式
第一行包含整数 TT,表示共有 TT 组测试数据。
每组数据第一行包含两个整数 n,mn,m。
接下来 mm 行,每行包含三个整数 t,x,yt,x,y,用来描述一条边的信息,其中 tt 表示边的状态,如果 t=0t=0,则表示边是无向边,如果 t=1t=1,则表示边是有向边。x,yx,y 表示这条边连接的两个端点,如果是有向边则边的方向是从 xx 指向 yy。
保证图中没有重边(给定了 (x,y)(x,y),就不会再次出现 (x,y)(x,y) 或出现 (y,x)(y,x))和自环(不会出现 x=yx=y 的情况)。
输出格式
对于每组数据,如果无法构造出有向无环图,则输出一行 NO。
否则,先输出一行 YES,随后 mm 行,每行包含两个整数 x,yx,y,用来描述最终构造成的有向无环图中的每条边的具体方向(xx 指向 yy),边的先后顺序随意。
注意,已经确定方向的边,不能更改方向。
如果答案不唯一,输出任意合理方案均可。
数据范围
对于前三个测试点,1≤n,m≤101≤n,m≤10。
对于全部测试点,1≤T≤200001≤T≤20000,2≤n≤2×1052≤n≤2×105,1≤m≤min(2×105,n(n−1)2)1≤m≤min(2×105,n(n−1)2),0≤t≤10≤t≤1,1≤x,y≤n1≤x,y≤n。
保证在一个测试点中,所有 nn 的和不超过 2×1052×105,所有 mm 的和不超过 2×1052×105。
输入样例:
4
3 1
0 1 3
5 5
0 2 1
1 1 5
1 5 4
0 5 2
1 3 5
4 5
1 1 2
0 4 3
1 3 1
0 2 3
1 2 4
4 5
1 4 1
1 1 3
0 1 2
1 2 4
1 3 2
输出样例:
YES
3 1
YES
2 1
1 5
5 4
2 5
3 5
YES
1 2
3 4
3 1
3 2
2 4
NO
#include <iostream> #include <algorithm> #include <cstring> using namespace std; const int N = 2e5 + 10; int n, m; int h[N], e[N], ne[N], d[N], idx; int q[N]; int S[N]; struct Edge { int x, y; }edges[N]; void add(int a, int b) // 添加一条边a->b { e[idx] = b, ne[idx] = h[a], h[a] = idx ++ ; } bool topsort() //拓扑排序 { int hh = 0, tt = -1; // d[i] 存储点i的入度 for (int i = 1; i <= n; i ++ ) if (!d[i]) q[ ++ tt] = i, S[i] = tt; while (hh <= tt) { int t = q[hh ++ ]; for (int i = h[t]; i != -1; i = ne[i]) { int j = e[i]; if (-- d[j] == 0) q[ ++ tt] = j, S[j] = tt; } } return tt == n - 1; } void solve() { scanf("%d%d", &n, &m); idx = 0; memset(d, 0, (n + 1) * 4); memset(h, -1, (n + 1) * 4); for (int i = 0; i < m; ++ i) { int t, a, b; scanf("%d%d%d", &t, &a, &b); if (t) add(a, b), ++ d[b]; edges[i] = {a, b}; } if (!topsort()) puts("NO"); else { puts("YES"); for (int i = 0; i < m; ++ i) { auto &t = edges[i]; if (S[t.x] < S[t.y]) printf("%d %d\n", t.x, t.y); else printf("%d %d\n", t.y, t.x); } } } int main() { int T = 1; scanf("%d", &T); while (T -- ) solve(); return 0; }

浙公网安备 33010602011771号