CF1385E Directing Edges
CF1385E Directing Edges
题目描述:
给定一个图,有无向边和有向边。对于无向边进行定向,问能否给出一个方案使得定向后的图是无环的,图不一定要联通。
我们先不考虑无向边,对于有向边组成的图,不妨进行一次拓扑排序找到每一个节点遍历的先后顺序。
我们先判掉有环的情况,也就是存在一条边 $u \to v$ 而且点 $u$ 的遍历时间比 $v$ 要晚。
之后考虑我们肯定可以构造出一种合法的图,也就是对于所有的无向边我们考虑连接的两个几点,只要保证边 $u \to v$ 而且点 $u$ 的遍历时间比 $v$ 早即可。
具体实现的时候因为图不一定联通,所以我们不妨对于每一个节点进行 $\tt dfs$ 在搜索完儿子之后再将自己加入。这样可以保证及时搜索节点的顺序不同也可以保证是拓扑序列。
之后取反即可,因为现在是逆着的拓扑序。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79
   | #include <bits/stdc++.h> using namespace std;
 
 
 
  #ifdef Fread char buf[1 << 21], *iS, *iT; #define gc() (iS == iT ? (iT = (iS = buf) + fread (buf, 1, 1 << 21, stdin), (iS == iT ? EOF : *iS ++)) : *iS ++) #define getchar gc #endif 
  template <typename T> void r1(T &x) { 	x = 0; 	char c(getchar()); 	int f(1); 	for(; c < '0' || c > '9'; c = getchar()) if(c == '-') f = -1; 	for(; '0' <= c && c <= '9';c = getchar()) x = (x * 10) + (c ^ 48); 	x *= f; }
  template <typename T,typename... Args> inline void r1(T& t, Args&... args) {     r1(t);  r1(args...); }
 
  const int maxn = 2e5 + 5; const int maxm = maxn << 1;
  vector<vector<int> > vc;
  void add(int u,int v) {     vc[u].push_back(v); } int n, m;
  struct Edge {     int opt, u, v; }E[maxn]; int tot(0);
  void Solve() {     int i, j;     r1(n, m); tot = 0;     vc.clear(), vc.resize(n + 1);     for(i = 1; i <= m; ++ i) {         int opt, u, v;         r1(opt, u, v);         if(opt == 1) add(u, v);         E[++ tot] = (Edge) {opt, u, v};     }     vector<int> vis(n + 1, 0), od, pos(n + 1, 0);     function<void(int)> dfs;     dfs = [&] (int p) {         vis[p] = 1;         for(int v : vc[p]) if(!vis[v]) dfs(v);         od.push_back(p);     };     for(i = 1; i <= n; ++ i) if(!vis[i]) dfs(i);     reverse(od.begin(), od.end());     for(i = 0; i < n; ++ i) pos[od[i]] = i;     for(i = 1; i <= n; ++ i) for(int v : vc[i]) if(pos[i] > pos[v]) return puts("NO"), void();     puts("YES");     for(i = 1; i <= m; ++ i) {         if(pos[E[i].u] > pos[E[i].v]) swap(E[i].u, E[i].v);         printf("%d %d\n", E[i].u, E[i].v);     }     return ; }
  signed main() {
 
      int i, j, T;     r1(T);     while(T --) Solve(); 	return 0; }
   |