POJ 3140 Contestants Division 树形dp

来源:互联网 发布:淘宝怎么更改退款金额 编辑:程序博客网 时间:2024/06/06 01:21

题意:

一个带权的树删去一条边使得分成的两部分权值和的差最小

分析:

dfs暴力枚举每一条边就好了

tips:inf 如果设为0x3f3f3f3f3f 会错 因为答案可能很大

ACcode:

#include <iostream>#include <cstring>#include <algorithm>#include <cstdio>#include <cmath>#include <cstring>#include <string>#include <vector>#define maxn 100005#define inf (((unsigned long long)(1)<<63)-1)#define ll long longusing namespace std;int n,m,tmp;struct N{    int to,next;}my[maxn<<1];int num[maxn];ll sum,ans,total,dp[maxn];int head[maxn],tot,cnt=1;void init(){    memset(head,-1,sizeof(head));    total=sum=tot=0;}void add(int u,int v){    my[tot].to=v;    my[tot].next=head[u];    head[u]=tot++;    ans=inf;}void dfs(int u,int fa){    for(int i=head[u];i!=-1;i=my[i].next){        int v=my[i].to;        if(fa==v)continue;        dfs(v,u);        ll tmp=total-2*dp[v];        if(tmp<0)tmp=-tmp;        ans=min(ans,tmp);        dp[u]+=dp[v];    }}int main(){    while(scanf("%d%d",&n,&m)&&n+m){        init();        for(int i=1;i<=n;++i){            scanf("%d",&num[i]);            total+=num[i];            dp[i]=num[i];        }        for(int i=1;i<n;++i){            int u,v;            scanf("%d%d",&u,&v);            add(u,v);            add(v,u);        }        dfs(1,-1);        printf("Case %d: %lld\n",cnt++,ans);    }    return 0;}


0 0
原创粉丝点击