CodeForces 219D Choosing Capital for Treeland (樹形dp)

題意是:給定n個點,n-1條有向邊。求 使該點到全部點改變邊方向最少,並輸出那些點。ios

題解:正向邊權值爲0,反向爲1.ide

第一次dfs記錄每一個點到全部子樹中須要改變的邊的條數。 (自下向上推)(優化下只需求出根節點到全部的點須要改變的邊的條數)優化

第二次dfs由父節點求子節點到全部點的須要改變的邊的條數。(自上向下)spa

  1 #include<cstdio>
  2 #include<cstring>
  3 #include<string>
  4 #include<iostream>
  5 #include<vector>
  6 using namespace std;
  7 const int N=200020;
  8 struct Point
  9 {
 10     int v,w;
 11 };
 12 vector<Point>V[N];
 13 int vis[N],dp[N];
 14 void init(int n)
 15 {
 16     for(int i=1;i<n;i++)
 17     {
 18         V[i].clear();
 19         vis[i]=0;
 20         dp[i]=0;
 21     }
 22 }
 23 int res=0;
 24 void dfs1(int s) //求根節點到全部點須要改變的邊的條數.
 25 {
 26     vis[s]=1;
 27     for(int i=0;i<(int)V[s].size();i++)
 28     {
 29         int x=V[s][i].v;
 30         int w=V[s][i].w;
 31         if(!vis[x])
 32         {
 33             dfs1(x);
 34             res+=w;
 35         }
 36     }
 37 }
 38 void dfs2(int s)  //第二次dfs,求節點到全部的點須要改變的邊的條數。
 39 {
 40     vis[s]=1;
 41     for(int i=0;i<(int)V[s].size();i++)
 42     {
 43         int x=V[s][i].v;
 44         int w=V[s][i].w;
 45         if(!vis[x])  //s爲父節點,x爲節點。
 46         {
 47             if(w==0)
 48             {
 49                 dp[x]=dp[s]+1; // s指向x。
 50             }
 51             else dp[x]=dp[s]-1; //x指向s;
 52             dfs2(x);
 53         }
 54     }
 55 }
 56 int main()
 57 {
 58     //freopen("Input.txt","r",stdin);
 59     int n,i;
 60     while(~scanf("%d",&n))
 61     {
 62         init(n);
 63         int a,b;
 64         Point tmp;
 65         for(i=1;i<n;i++)
 66         {
 67             scanf("%d%d",&a,&b);
 68             tmp.v=b;tmp.w=0;  //正向邊
 69             V[a].push_back(tmp);
 70             tmp.v=a;tmp.w=1;   //反向邊。
 71             V[b].push_back(tmp);
 72         }
 73         res=0;
 74         dfs1(1);
 75 //        for(i=1;i<=n;i++)
 76 //           printf("%d \n",dp[i]);
 77         memset(vis,0,sizeof(vis));
 78         dp[1]=res;
 79         dfs2(1);
 80         int Min=0x7fffffff;
 81         int j;
 82         for(i=1;i<=n;i++)
 83         {
 84             if(Min>=dp[i]) { Min=dp[i];j=i;}
 85             //printf("%d  ---> %d  \n",i,dp[i]);
 86         }
 87         printf("%d\n",Min);
 88         for(i=1;i<=n;i++)
 89         {
 90             if(i==j)
 91             {
 92                 printf("%d\n",i);
 93                 break;
 94             }
 95             if(dp[i]==Min)
 96               printf("%d ",i);
 97         }
 98     }
 99     return 0;
100 }
View Code
相關文章
相關標籤/搜索