[codeforces219D]Choosing Capital for Treeland树形dp

题意:给出一棵树,带有向边,找出某个点到达所有点需要反转的最少的边。

解题关键:和求树的直径的思路差不多,将求(父树-子树)的最大值改为求特定值。依然是两次dfs,套路解法。

对树形dp的理解:树形dp其实就是将树进行暴力搜索,只是需要理解状态的概念。那些状态已经完成,需要从底还是从顶开始搜索。

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 #include<cstdlib>
 5 #include<cmath>
 6 #include<iostream>
 7 using namespace std;
 8 typedef long long ll;
 9 const int maxn=1e6+3;
10 const int inf=0x3f3f3f3f;
11 int head[maxn],tot,n,m,sum;
12 int dp[maxn][3],cnt[maxn];
13 struct edge{
14     int to;
15     int nxt;
16     int w;
17 }e[maxn<<2];
18 void add_edge(int u,int v,int w){
19     e[tot].to=v;
20     e[tot].w=w;
21     e[tot].nxt=head[u];
22     head[u]=tot++;
23 }
24 
25 void dfs1(int u,int fa){
26     for(int i=head[u];i!=-1;i=e[i].nxt){
27         int v=e[i].to;
28         if(v==fa) continue;
29         dfs1(v,u);
30         dp[u][0]+=dp[v][0]+e[i].w;
31     }
32 }
33 
34 void dfs2(int u,int fa){
35     for(int i=head[u];i!=-1;i=e[i].nxt){
36         int v=e[i].to;
37         if(v==fa) continue;
38         dp[v][1]=dp[u][0]-dp[v][0]+dp[u][1];
39         if(e[i].w==0) dp[v][1]+=1;
40         else dp[v][1]-=1;
41         dfs2(v,u);
42     }
43 }
44 
45 inline int read(){
46     char k=0;char ls;ls=getchar();for(;ls<'0'||ls>'9';k=ls,ls=getchar());
47     int x=0;for(;ls>='0'&&ls<='9';ls=getchar())x=(x<<3)+(x<<1)+ls-'0';
48     if(k=='-')x=0-x;return x;
49 }
50 
51 int main(){
52     int k=0;
53     while(scanf("%d",&n)!=EOF){
54         memset(head,-1,sizeof head);
55         tot=0;
56         int a,b;
57         /*for(int i=1;i<n;i++){
58             cnt[i]=read();
59             sum+=1ll*cnt[i];
60         }*/
61         for(int i=0;i<n-1;i++){
62             a=read();
63             b=read();
64             add_edge(a,b,0);
65             add_edge(b,a,1);
66         }
67         dfs1(1,-1);
68         dfs2(1,-1);
69         for(int i=1;i<=n;i++){
70             dp[i][2]=dp[i][0]+dp[i][1];
71         }
72         int min1=inf;
73         for(int i=1;i<=n;i++){
74             min1=min(dp[i][2],min1);
75         }
76         cout<<min1<<"
";
77         for(int i=1;i<=n;i++){
78         //    cout<<dp[i][2]<<" ";
79             if(dp[i][2]==min1) cout<<i<<" ";
80         }
81     }
82     return 0;
83     return 0;
84 }
原文地址:https://www.cnblogs.com/elpsycongroo/p/7421068.html