POJ 3140 Contestants Division 【树形DP】

时间:2023-03-08 19:37:49

<题目链接>

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

解题分析:

比较基础的树形DP。

 #include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std; typedef long long ll;
#define INF 0x7fffffff7fffffff
#define clr(a,b) memset(a,b,sizeof(a))
#define rep(i,s,t) for(int i=s;i<=t;i++)
const int N = 1e5+;
struct Edge{
int to,nxt;
}edge[N<<];
int n,m,cnt,head[N];
ll val[N],dp[N],ans,sum; ll llabs(ll a){return a>=?a:(-a);} void init(){
cnt=;sum=;clr(head,-);
}
void addedge(int u,int v){
edge[cnt].to=v,edge[cnt].nxt=head[u];
head[u]=cnt++;
}
void dfs(int u,int pre){
dp[u]=val[u];
for(int i=head[u];~i;i=edge[i].nxt){
int v = edge[i].to;
if(v == pre)continue;
dfs(v,u);
dp[u]+=dp[v];
}
ans=min(ans,llabs(dp[u]-(sum-dp[u]))); //记录最小的差值
}
int main(){
int ncase=;
while(scanf("%d%d",&n,&m)!=EOF,n||m){
init();
rep(i,,n)scanf("%lld",&val[i]),sum+=val[i];
rep(i,,m){
int u,v;scanf("%d%d",&u,&v);
addedge(u,v);addedge(v,u);
}
ans=INF;
dfs(,-);
printf("Case %d: %lld\n",++ncase,ans);
}
}

2019-02-03