Codeforces Round #656 (Div. 3) E - Directing Edges
阿新 • • 發佈:2020-07-18
連結
https://codeforces.com/contest/1385/problem/E
題意
給定一張圖,既有 有向邊,也有 無向邊,要求給每個無向邊加上方向使得最終整張圖無環。
若存在方案輸出Yes,並輸出每條無向邊的方向,否則輸出No
思路
先說結論,拋開無向邊,如果有向邊構成的圖本身成環,那麼明顯是No,否則一定是Yes
如何判斷是否成環呢,我們可以利用拓撲序,假設存在一條有向邊A->B,如果圖中有環,那麼B的拓撲序應該小於A,也即存在一條B到A的路徑
有了拓撲序我們就可以利用它來輸出Yes時的方案了
對於每條無向邊AB,假設A的拓撲序小於B,那麼該邊的方向就應該為A->B,否則就會如上所說成環
程式碼
#include <bits/stdc++.h> using namespace std; vector<int> ord; vector<int> used; vector<vector<int>> g; void dfs(int v) { used[v] = 1; for (auto to : g[v]) { if (!used[to]) dfs(to); } ord.push_back(v); } int main() { #ifdef _DEBUG freopen("input.txt", "r", stdin); // freopen("output.txt", "w", stdout); #endif int t; cin >> t; while (t--) { int n, m; cin >> n >> m; g = vector<vector<int>>(n); vector<pair<int, int>> edges; for (int i = 0; i < m; ++i) { int t, x, y; cin >> t >> x >> y; --x, --y; if (t == 1) { g[x].push_back(y); } edges.push_back({x, y}); } ord.clear(); used = vector<int>(n); for (int i = 0; i < n; ++i) { if (!used[i]) dfs(i); } vector<int> pos(n); reverse(ord.begin(), ord.end()); for (int i = 0; i < n; ++i) { pos[ord[i]] = i; } bool bad = false; for (int i = 0; i < n; ++i) { for (auto j : g[i]) { if (pos[i] > pos[j]) bad = true; } } if (bad) { cout << "NO" << endl; } else { cout << "YES" << endl; for (auto [x, y] : edges) { if (pos[x] < pos[y]) { cout << x + 1 << " " << y + 1 << endl; } else { cout << y + 1 << " " << x + 1 << endl; } } } } return 0; }
vector太好用了,就直接把題解的程式碼貼上來了(