poj 3140-Contestants Division解题报告


链接:http://poj.org/problem?id=3140

这道题是说,给出一棵树,每个节点有一个权值,要求去掉一条边所能获得的两棵树的最小的权值差,其实不能说是dp因为除了最后一步涉及到了取最小之外,其他的地方都是在枚举而已,没有什么状态转移之类的东西存在,只能说是一道简单的树形的搜索

View Code
 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #define N 100005
 5 #define M 1000005
 6 using namespace std;
 7 int head[N];
 8 struct edge
 9 {
10     int v;
11     int next;
12 };
13 edge e[M];
14 int t;
15 long long v[N];
16 long long dp[N];
17 bool used[N];
18 void init()
19 {
20     memset(head,-1,sizeof(head));
21     memset(used,0,sizeof(used));
22     memset(dp,0,sizeof(dp));
23     t=0;
24 }
25 void add(int x,int y)
26 {
27     e[t].v=x;
28     e[t].next=head[y];
29     head[y]=t++;
30     e[t].v=y;
31     e[t].next=head[x];
32     head[x]=t++;
33 }
34 void dfs(int u)
35 {
36     used[u]=true;
37     dp[u]=v[u];
38     int i;
39     for(i=head[u];i>=0;i=e[i].next)
40     {
41         if(!used[e[i].v])
42         {
43             dfs(e[i].v);
44             dp[u]+=dp[e[i].v];
45         }
46     }
47 }
48 long long abs(long long x)
49 {
50     return x>=0?x:-x;
51 }
52 long long min(long long a,long long b)
53 {
54     return a<b?a:b;
55 }
56 int main()
57 {
58     int n,m;
59     int i,j,k;
60     int icase=1;
61     while(scanf("%d%d",&n,&m)&&(m||n))
62     {
63         init();
64         long long all=0;
65         long long ans;
66         for(i=1;i<=n;i++)
67         {
68             scanf("%lld",&v[i]);
69             all+=v[i];
70         }
71         while(m--)
72         {
73             scanf("%d%d",&j,&k);
74             add(j,k);
75         }
76         dfs(1);
77         printf("Case %d: ",icase++);
78         ans=abs(all-2*dp[1]);
79         for(i=2;i<=n;i++)
80         ans=min(ans,abs(all-2*dp[i]));
81         printf("%lld\n",ans);
82     }
83     return 0;
84 }
posted @ 2012-04-26 19:11  zhenhai  阅读(182)  评论(0编辑  收藏  举报