Codeforces Round #656 (Div. 3) E. Directing Edges(拓撲排序)
阿新 • • 發佈:2020-12-30
題目傳送門
首先發現初始圖五有向環的話那麼肯定是“YES”,否則是“NO”。然後找到一種滿足要求地建樹規則即可。這裡採用拓撲排序建樹,先dfs找出目前點的拓撲序編號,要求從編號小的連向編號大的,然後根據編號大小給無向邊確定方向。這樣一定滿足要求,因為如果一開始沒有有向環,那麼沿著有向邊走點的拓撲序編號一定不斷變大,所以不可能產生環。
#include<cstdio> #include<set> #include<vector> #include<algorithm> using namespace std; typedef long long ll; const int N = 1e6 + 50; int T, n, m, cnt; int num[N]; bool used[N]; vector<vector<int> > d; vector<int> Topu; void dfs(int u){ used[u] = 1; for(auto &x : d[u]) if(!used[x]) dfs(x); Topu.emplace_back(u); } int main(){ scanf("%d", &T); while(T--){ scanf("%d%d", &n, &m); cnt = 0; bool ok = 1; Topu.clear(); vector<pair<int, int> > e; d = vector<vector<int> >(n + 1); for(int i = 1; i <= n; ++i) used[i] = 0; for(int i = 1, t, x, y; i <= m; ++i){ scanf("%d%d%d", &t, &x, &y); if(t == 1) d[x].emplace_back(y); e.emplace_back(make_pair(x, y)); } for(int i = 1; i <= n; ++i) if(!used[i]) dfs(i); for(int i = n - 1; ~i; --i) num[Topu[i]] = ++cnt; for(int i = 1; i <= n; ++i){ for(auto &x : d[i]) if(num[i] > num[x]) ok = 0; } if(!ok) puts("NO"); else{ puts("YES"); for(auto &tt : e){ int x = tt.first, y = tt.second; if(num[x] > num[y]) printf("%d %d\n", y, x); else printf("%d %d\n", x, y); } } } return 0; }