【Codeforces 1385 E】Directing Edges
题目链接
翻译
给你一个 \(n\) 个节点 \(m\) 条边的图,但是有一些边的方向还没有确定。
问你能否将其中没有确定方向的边确定了,使得最后形成的整张图没有环。
题解
一说就会做的题。
先将已经确定了方向的边作为图的边,然后在这个有向图的基础上跑拓扑排序。
记录下每个节点在拓扑排序中的序号。
然后在最后输出答案的时候,对于没有确定方向的边,将其方向改为从拓扑排序序号小的节点指向序号大的节点。
这样,肯定是满足拓扑排序的要求的,即谁在谁前面先输出。
然后如果拓扑排序做不了的话 (已经确定方向的边生成的有向图的基础上做的) ,说明已经有环了。则无解。
否则按照上面的方案输出就好,一定有解。
代码
#include <bits/stdc++.h>
using namespace std;
const int M = 2e5;
struct abc{
int p,x,y;
};
int n, m;
abc a[M + 10];
vector<int> g[M + 10];
int du[M + 10], order[M + 10];
queue<int> dl;
int main(){
#ifdef LOCAL_DEFINE
freopen("E://9.AlgorithmCompetition//Visitor.txt","r",stdin);
#endif
ios::sync_with_stdio(0),cin.tie(0);
int T;
cin >> T;
while (T--){
cin >> n >> m;
for (int i = 1;i <= n; i++){
g[i].clear();
du[i] = 0;
}
for (int i = 1;i <= m; i++){
int p,x,y;
cin >> p >> x >> y;
if (p == 1){
g[x].push_back(y);
du[y]++;
}
a[i].p = p;
a[i].x = x;
a[i].y = y;
}
for (int i = 1;i <= n; i++)
if (du[i] == 0){
dl.push(i);
}
int cur = 0;
while (!dl.empty()){
int x = dl.front();dl.pop();
order[x] = ++cur;
for (int i = 0;i < (int)g[x].size(); i++){
int y = g[x][i];
du[y]--;
if (du[y] == 0){
dl.push(y);
}
}
}
if (cur!=n){
cout << "NO" << endl;
}else{
cout << "YES" << endl;
for (int i = 1;i <= m; i++){
if (a[i].p == 0 && order[a[i].x] > order[a[i].y]){
swap(a[i].x,a[i].y);
}
cout << a[i].x <<" "<<a[i].y << endl;
}
}
}
return 0;
}