POJ 3140 Contestants Division(树形DP)
题意:给一颗无向树,问删除某一条边后两个连通分支的最小差异值
思路:也是和前几题差不多的思路..直接DFS一波就可以了...
#include <cstdio> #include <queue> #include <cstring> #include <iostream> #include <cstdlib> #include <algorithm> #include <vector> #include <map> #include <string> #include <set> #include <ctime> #include <cmath> #include <cctype> #define fab(a) (a)>0?(a):0-(a) using namespace std; #define maxn 100005 #define LL long long #define inf 1e14 int cas=1,T; vector<int>e[maxn]; LL a[maxn]; LL dp[maxn]; int n,m; LL minx ; LL sum; void dfs(int u,int fa) { dp[u]=a[u]; for (int i = 0;i<e[u].size();i++) { int v = e[u][i]; if (v==fa) continue; dfs(v,u); dp[u]+=dp[v]; } minx = min(minx,fab(sum-dp[u]-dp[u])); } int main() { while (scanf("%d%d",&n,&m) && n+m) { minx = inf; sum = 0; for (int i = 0;i<=n;i++) e[i].clear(); for (int i = 1;i<=n;i++) scanf("%lld",&a[i]),sum+=a[i]; for (int i = 1;i<n;i++) { int u,v; scanf("%d%d",&u,&v); e[u].push_back(v); e[v].push_back(u); } memset(dp,0,sizeof(dp)); dfs(1,-1); printf("Case %d: %lld\n",cas++,minx); } //freopen("in","r",stdin); //scanf("%d",&T); //printf("time=%.3lf",(double)clock()/CLOCKS_PER_SEC); return 0; }