Codeforces 219D Choosing Capital for Treeland

http://codeforces.com/problemset/problem/219/D

题目大意:

给出一棵树,但是它的边是有向边,选择一个城市,问最少调整多少条边的方向能使一个选中城市可以到达所有的点,输出最小的调整的边数,和对应的点。

思路:先预处理一个点为根的代价,然后去dfs移动,总复杂度是O(n)

 1 #include<cstdio>
 2 #include<cmath>
 3 #include<algorithm>
 4 #include<cstring>
 5 #include<iostream>
 6 int tot,go[400005],next[400005],first[200005],id[400005];
 7 int son[200005],f[200005],v[200005],n;
 8 int read(){
 9     int t=0,f=1;char ch=getchar();
10     while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();}
11     while ('0'<=ch&&ch<='9'){t=t*10+ch-'0';ch=getchar();}
12     return t*f;
13 }
14 void insert(int x,int y,int Id){
15     tot++;
16     go[tot]=y;
17     next[tot]=first[x];
18     first[x]=tot;
19     id[tot]=Id;
20 }
21 void add(int x,int y){
22     insert(x,y,1);insert(y,x,-1);
23 }
24 void dfs(int x,int fa){
25     son[x]=0;
26     for (int i=first[x];i;i=next[i]){
27         int pur=go[i];
28         if (pur==fa) continue;
29         if (id[i]==-1) v[pur]=1;
30         dfs(pur,x);
31         son[x]+=son[pur]+v[pur];
32     }
33 }
34 void dp(int x,int fa){
35     for (int i=first[x];i;i=next[i]){
36         int pur=go[i];
37         if (pur==fa) continue;
38         if (id[i]==1) f[pur]=f[x]+1;
39         else f[pur]=f[x]-1;
40         dp(pur,x);
41     }
42 }
43 int main(){
44     n=read();
45     for (int i=1;i<n;i++){
46         int x=read(),y=read();
47         add(x,y);
48     }
49     dfs(1,0);
50     f[1]=son[1];
51     dp(1,0);
52     int ans=n;
53     for (int i=1;i<=n;i++) ans=std::min(ans,f[i]);
54     printf("%d
",ans);
55     for (int i=1;i<=n;i++) if (ans==f[i])
56      printf("%d ",i);
57     return 0;
58 }
原文地址:https://www.cnblogs.com/qzqzgfy/p/5630269.html