标签:
题目是给一张边有向的树形图。要选出首都的点,首都要都能走到其他点,因此要反转一些边的方向。问可以选哪几个点作为首都,使它们所需反转边的数量最少。
这题挺好想的,因为做过HDU2196。
感觉又学到一种树形DP的新姿势:分别考虑点往下的子树和点往上的父亲部分。
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 using namespace std; 5 #define INF (1<<30) 6 #define MAXN 222222 7 struct Edge{ 8 int u,v,w,next; 9 }edge[MAXN<<1]; 10 int NE,head[MAXN]; 11 void addEdge(int u,int v,int w){ 12 edge[NE].u=u; edge[NE].v=v; edge[NE].w=w; 13 edge[NE].next=head[u]; head[u]=NE++; 14 } 15 int d[2][MAXN]; 16 void dfs0(int u,int fa){ 17 for(int i=head[u]; i!=-1; i=edge[i].next){ 18 int v=edge[i].v; 19 if(v==fa) continue; 20 dfs0(v,u); 21 d[0][u]+=d[0][v]+edge[i].w; 22 } 23 } 24 void dfs1(int u,int fa){ 25 for(int i=head[u]; i!=-1; i=edge[i].next){ 26 int v=edge[i].v; 27 if(v==fa) continue; 28 d[1][v]=d[0][u]-d[0][v]-edge[i].w+d[1][u]+edge[i^1].w; 29 dfs1(v,u); 30 } 31 } 32 int main(){ 33 memset(head,-1,sizeof(head)); 34 int n,a,b; 35 scanf("%d",&n); 36 for(int i=1; i<n; ++i){ 37 scanf("%d%d",&a,&b); 38 addEdge(a,b,0); addEdge(b,a,1); 39 } 40 dfs0(1,1); 41 dfs1(1,1); 42 int res=INF; 43 for(int i=1; i<=n; ++i) res=min(res,d[0][i]+d[1][i]); 44 printf("%d\n",res); 45 for(int i=1; i<=n; ++i){ 46 if(res==d[0][i]+d[1][i]){ 47 printf("%d ",i); 48 } 49 } 50 return 0; 51 }
Codeforces 219D Choosing Capital for Treeland(树形DP)
标签:
原文地址:http://www.cnblogs.com/WABoss/p/5267944.html