POJ 3140 Contestants Division 【树形DP】

<题目链接>

题目大意:
给你一棵树,让你找一条边,使得该边的两个端点所对应的两颗子树权值和相差最小,求最小的权值差。

解题分析:

比较基础的树形DP。

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <algorithm>
 4 using namespace std;
 5 
 6 typedef long long ll;
 7 #define INF 0x7fffffff7fffffff
 8 #define clr(a,b) memset(a,b,sizeof(a))
 9 #define rep(i,s,t) for(int i=s;i<=t;i++)
10 const int N = 1e5+10;
11 struct Edge{
12     int to,nxt;
13 }edge[N<<1];
14 int n,m,cnt,head[N];
15 ll val[N],dp[N],ans,sum;
16 
17 ll llabs(ll a){return a>=0?a:(-a);}
18 
19 void init(){
20     cnt=0;sum=0;clr(head,-1);
21 }
22 void addedge(int u,int v){
23     edge[cnt].to=v,edge[cnt].nxt=head[u];
24     head[u]=cnt++;
25 }
26 void dfs(int u,int pre){
27     dp[u]=val[u];
28     for(int i=head[u];~i;i=edge[i].nxt){
29         int v = edge[i].to;
30         if(v == pre)continue;
31         dfs(v,u);
32         dp[u]+=dp[v];
33     }
34     ans=min(ans,llabs(dp[u]-(sum-dp[u])));     //记录最小的差值
35 }
36 int main(){
37     int ncase=0;
38     while(scanf("%d%d",&n,&m)!=EOF,n||m){
39         init();
40         rep(i,1,n)scanf("%lld",&val[i]),sum+=val[i];
41         rep(i,1,m){
42             int u,v;scanf("%d%d",&u,&v);
43             addedge(u,v);addedge(v,u);
44         }
45         ans=INF;
46         dfs(1,-1);
47         printf("Case %d: %lld\n",++ncase,ans);
48     }
49 }

2019-02-03 

猜你喜欢

转载自www.cnblogs.com/00isok/p/10350669.html