CodeForces 219D Choosing Capit

题目链接:http://codeforces.com/contest/219/problem/D

题目大意:

  给定一个n个节点的数和连接n个节点的n - 1条有向边,现在要选定一个节点作为起始节点,从这个点出发需要能走到其余每个节点,途中必然要调整有向边的方向,请求出当选定哪些节点作为初始节点时,所要调整的有向边最少,输出最小调整的边数和这些节点。

分析:

  Hint:城市结构是树型结构。

代码如下:

  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 }
View Code

 

posted @ 2019-04-22 19:50  梦樱羽  阅读(124)  评论(0编辑  收藏  举报
Live2D