题目链接:http://codeforces.com/contest/219/problem/D
题目大意:
给定一个n个节点的数和连接n个节点的n - 1条有向边,现在要选定一个节点作为起始节点,从这个点出发需要能走到其余每个节点,途中必然要调整有向边的方向,请求出当选定哪些节点作为初始节点时,所要调整的有向边最少,输出最小调整的边数和这些节点。
分析:
Hint:城市结构是树型结构。
代码如下:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 #define rep(i,n) for (int i = 0; i < (n); ++i) 5 #define For(i,s,t) for (int i = (s); i <= (t); ++i) 6 #define rFor(i,t,s) for (int i = (t); i >= (s); --i) 7 #define foreach(i,c) for (__typeof(c.begin()) i = c.begin(); i != c.end(); ++i) 8 #define rforeach(i,c) for (__typeof(c.rbegin()) i = c.rbegin(); i != c.rend(); ++i) 9 10 #define pr(x) cout << #x << " = " << x << " " 11 #define prln(x) cout << #x << " = " << x << endl 12 13 #define LOWBIT(x) ((x)&(-x)) 14 15 #define ALL(x) x.begin(),x.end() 16 #define INS(x) inserter(x,x.begin()) 17 18 #define ms0(a) memset(a,0,sizeof(a)) 19 #define msI(a) memset(a,inf,sizeof(a)) 20 #define msM(a) memset(a,-1,sizeof(a)) 21 22 #define pii pair<int,int> 23 #define piii pair<pair<int,int>,int> 24 #define mp make_pair 25 #define pb push_back 26 #define fi first 27 #define se second 28 29 inline int gc(){ 30 static const int BUF = 1e7; 31 static char buf[BUF], *bg = buf + BUF, *ed = bg; 32 33 if(bg == ed) fread(bg = buf, 1, BUF, stdin); 34 return *bg++; 35 } 36 37 inline int ri(){ 38 int x = 0, f = 1, c = gc(); 39 for(; c<48||c>57; f = c=='-'?-1:f, c=gc()); 40 for(; c>47&&c<58; x = x*10 + c - 48, c=gc()); 41 return x*f; 42 } 43 44 typedef long long LL; 45 typedef unsigned long long uLL; 46 const int inf = 1e9 + 9; 47 const LL mod = 1e9 + 7; 48 const int maxN = 2e5 + 7; 49 50 struct Node{ 51 vector< pii > next; 52 }; 53 54 int n, ans; 55 // dp[i]表示以i号城市为首都所要反转的道路数 56 int dp[maxN]; 57 int vis[maxN]; 58 Node nodes[maxN]; 59 queue< int > Q; 60 61 // 求dp[x] 62 inline int dfs(int x) { 63 if(nodes[x].next.empty()) return 0; 64 65 int ret = 0; 66 foreach(i, nodes[x].next) { 67 int y = i->fi, z = i->se; 68 if(vis[y]) continue; 69 vis[x] = 1; 70 if(z == -1) ++ret; 71 ret += dfs(y); 72 } 73 return ret; 74 } 75 76 // 如果dp[i]已知,假设j号城市与i号城市相连,由于整个城市图是树形结构, 77 // 因此dp[j]与dp[i]除了他们的连线有分歧,其余应该反转的道路数量都是一样的 78 // 因此可由已算出来的1号城市为中心,向外做BFS 79 inline void bfs() { 80 ms0(vis); 81 vis[1] = 1; 82 Q.push(1); 83 ans = dp[1]; 84 85 while(!Q.empty()) { 86 int tmp = Q.front(); 87 Q.pop(); 88 89 foreach(i, nodes[tmp].next) { 90 int y = i->fi, z = i->se; 91 if(vis[y]) continue; 92 vis[y] = 1; 93 dp[y] = dp[tmp] + z; 94 ans = min(ans, dp[y]); 95 Q.push(y); 96 } 97 } 98 } 99 100 int main(){ 101 while(cin >> n) { 102 ms0(vis); 103 rep(i, n + 1) nodes[i].next.clear(); 104 rep(i, n-1) { 105 int x, y; 106 cin >> x >> y; 107 nodes[x].next.push_back(mp(y, 1)); 108 nodes[y].next.push_back(mp(x, -1)); 109 } 110 dp[1] = dfs(1); 111 112 bfs(); 113 114 cout << ans << endl; 115 For(i, 1, n) if(ans == dp[i]) cout << i << " "; 116 cout << endl; 117 } 118 return 0; 119 }