当前位置: 代码迷 >> 综合 >> poj-3140-树形dp
  详细解决方案

poj-3140-树形dp

热度:64   发布时间:2023-12-19 10:58:10.0

虽然把这个题目分类到树形dp里面,但是它一点都不像树形dp。。。

直接枚举所有的边,看看去掉这条边之后的差值,寻找其中的最小值。

注意long long;

#include<iostream>
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<iostream>
#include<vector>
#include<set>
#include<string>
#define maxn 110000
using namespace std;
vector<int>old[maxn];
vector<int>now[maxn];
int vis[maxn];
long long val[maxn];
long long dp[maxn];
long long  minn,sum;
void change(int x)
{int i;vis[x]=1;for(i=0;i<old[x].size();i++){if(vis[old[x][i]])continue;now[x].push_back(old[x][i]);change(old[x][i]);}
}
void dfs(int x)
{dp[x]=val[x];for(int i=0;i<now[x].size();i++){int y=now[x][i];dfs(y);dp[x]=dp[x]+dp[y];}
}
void dps(int x)
{for(int i=0;i<now[x].size();i++){int y=now[x][i];dps(y);long long cha;cha=sum-dp[y]-dp[y];if(cha<0)cha=-cha;minn=min(minn,cha);}
}
int main()
{int i,n,j,m;int a,b;int cnt;cnt=0;while(~scanf("%d%d",&n,&m)&&(n||m)){cnt++;sum=0;memset(dp,0,sizeof(dp));for(i=1;i<=n;i++){scanf("%lld",&val[i]);sum+=val[i];}memset(vis,0,sizeof(vis));for(i=0;i<=n;i++){old[i].clear();now[i].clear();}for(i=1; i<n; i++){scanf("%d%d",&a,&b);old[a].push_back(b);old[b].push_back(a);}change(1);dfs(1);minn=sum;dps(1);printf("Case %d: %lld\n",cnt,minn);}return 0;
}