拓扑排序的性质
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
拓扑排序的性质
拓扑排序的性质:排完序之后,若最后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
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(); return0;
}。