POJ 3140 Contestants Division
题目大意:
给出一棵树,求去掉一条边之后两棵子树节点权值和作差的最小值。
解题思路:
这不知道怎么用树形DP做,只是个DFS就过了。还手残了一次。思路具体看代码。
下面是代码:
#include <stdio.h> #include <string.h> #include <algorithm> #include <iostream> #include <math.h> #include <stdlib.h> #include <vector> #include <string> #include <map> #include <queue> using namespace std; int min(int a,int b) { if(a>b)a=b; return a; } int max(int a,int b) { if(a<b)a=b; return a; } struct node { int to,next; } edge[100005*2]; int n,m,cnt,head[100005]; long long weight[100005],min1,sum; const long long inf = 100000000000000ll; bool vis[100005]; void addedge(int u,int v) { edge[cnt].to=v; edge[cnt].next=head[u]; head[u]=cnt++; edge[cnt].to=u; edge[cnt].next=head[v]; head[v]=cnt++; } bool chack(int src) { int t=head[src]; while(t!=-1) { if(!vis[edge[t].to])return true; t=edge[t].next; } return false; } long long llaabs(long long num) { if(num<0)num=-num; return num; } long long dfs(int src) { long long ans=weight[src],temp; vis[src]=true; if(chack(src)) { int t=head[src]; while(t!=-1) { if(!vis[edge[t].to]) { temp=dfs(edge[t].to); min1=min(min1,llaabs(sum-temp-temp)); ans+=temp; } t=edge[t].next; } } return ans; } int main() { int case1=1; while(scanf("%d%d",&n,&m),n||m) { cnt=0; int u,v; min1=inf; sum=0; memset(vis,false,sizeof(vis)); memset(head,-1,sizeof(head)); for(int i=1; i<=n; i++) { scanf("%lld",&weight[i]); sum+=weight[i]; } for(int i=0; i<m; i++) { scanf("%d%d",&u,&v); addedge(u,v); } dfs(1); printf("Case %d: %lld\n",case1++,min1); } return 0; }