CodeForces 1385E. Directing Edges(拓撲排序)
阿新 • • 發佈:2020-07-21
題意:你被給予了n個點m條邊。不保證這個圖是否聯通。一些邊已經被定向了,並且你無法改變它們的方向。一些邊還沒有定向,你需要為這些邊選擇一些方向。你需要給這些沒有定向的邊定一個方向,使得這個圖是有向無環圖。
分析:將所有邊存在一個數組裡,然後對有向圖的邊進行拓撲排序,得到所有頂點依次出現的順序,我們用一個數組\(pos\)記錄。然後判斷pos[]陣列的大小,依次輸出方案。拓撲排序可以判斷這個圖是否有環。
#include <iostream> #include <cstdio> #include <cstring> #include <string> #include <vector> #include <algorithm> using namespace std; const int N = 200005; int h[N], e[N * 2], ne[N * 2], idx; int d[N], q[N]; int pos[N]; int n, m; vector<pair<int, int>> edges; void add(int a, int b) { e[idx] = b, ne[idx] = h[a], h[a] = idx++; } bool topsort() { int hh = 0, tt = -1; for (int i = 1; i <= n; ++i) { if (d[i] == 0) { q[++tt] = i; } } while (hh <= tt) { int t = q[hh++]; for (int i = h[t]; i != -1; i = ne[i]) { int j = e[i]; --d[j]; if (d[j] == 0) { q[++tt] = j; } } } return tt == n - 1; } int main() { int t; scanf("%d", &t); while (t--) { memset(h, -1, sizeof h); idx = 0; scanf("%d%d", &n, &m); int ty; int u, v; for (int i = 1; i <= m; ++i) { scanf("%d%d%d", &ty, &u, &v); if (ty == 1) { add(u, v); ++d[v]; } edges.push_back({ u, v }); } bool flag = topsort(); if (!flag) { puts("NO"); } else { puts("YES"); for (int i = 0; i < n; ++i) { pos[q[i]] = i + 1; } //給每條邊定向 for (auto [x, y] : edges) { if (pos[x] < pos[y]) { printf("%d %d\n", x, y); } else { printf("%d %d\n", y, x); } } } for (int i = 0; i <= n; ++i) { d[i] = 0; } edges.clear(); } return 0; }