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
作者:is_ok
出处:http://www.cnblogs.com/00isok/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。