Codeforces Round #135 (Div. 2)D. Choosing Capital for Treeland
题意:n个点,n-1个边,有向的,问当以某个点为起点,到其他点的话要改变多少个边的方向
思路:题目给的边价值为0,反向的价值为1,f[i]表示该点到他的子节点需要改变的边,g[i]为到他上方需要改变的,跑2遍图
1 #include<bits/stdc++.h> 2 using namespace std; 3 const int N=2e5+10; 4 5 struct node{ 6 int to,next,val; 7 }e[N*2]; 8 int head[N],tot; 9 int f[N],g[N]; 10 11 void init(){ 12 memset(head,-1,sizeof(head)); 13 tot=0; 14 } 15 16 void add(int u,int v,int w){ 17 e[tot].to=v;e[tot].next=head[u];e[tot].val=w; 18 head[u]=tot++; 19 } 20 21 void dfs1(int u,int fa){ 22 for(int i=head[u];i!=-1;i=e[i].next){ 23 int v=e[i].to,w=e[i].val; 24 if(v==fa) continue; 25 // cout<<u<<" "<<v<<" "<<w<<endl; 26 dfs1(v,u); 27 f[u]+=f[v]+w; 28 } 29 } 30 int Min=1e9+7; 31 void dfs2(int u,int fa){ 32 Min=min(Min,f[u]+g[u]); 33 for(int i=head[u];i!=-1;i=e[i].next){ 34 int v=e[i].to,w=e[i].val; 35 if(v==fa) continue; 36 g[v]=g[u]+f[u]-f[v]+(w==0?1:-1); 37 dfs2(v,u); 38 } 39 } 40 41 int main(){ 42 int n; 43 int x,y; 44 init(); 45 scanf("%d",&n); 46 for(int i=1;i<n;i++){ 47 scanf("%d%d",&x,&y); 48 add(x,y,0); 49 add(y,x,1); 50 } 51 dfs1(1,0); 52 dfs2(1,0); 53 cout<<Min<<endl; 54 for(int i=1;i<=n;i++){ 55 if(f[i]+g[i]==Min) 56 printf("%d ",i); 57 } 58 printf("\n"); 59 }