poj3140(树的dfs)

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

题意:给定一棵n棵节点的树,求删去某条边后两个分支的最小差异值。

分析:num[u]表示以u点为根节点的子树的总人数,那么不在该子树的人数和为sum-num[u].dfs遍历一遍即可。

#include <cstdio>
#include <cstring>
#include <cmath>
#include <iostream>
#include <algorithm>
#include <queue>
#include <cstdlib>
#include <stack>
#include <vector>
#include <set>
#include <map>
#define LL long long
#define mod 1000000007
#define inf 0x3f3f3f3f
#define N 100010
#define clr(a) (memset(a,0,sizeof(a)))
using namespace std;
struct edge
{
int next,v;
edge(){}
edge(int v,int next):v(v),next(next){}
}e[N*];
int head[N],tot,n,m;
LL ans,sum,num[N];
LL Abs(LL a)
{
return a>?a:-a;
}
void addedge(int u,int v)
{
e[tot]=edge(v,head[u]);
head[u]=tot++;
}
void dfs(int u,int fa)
{
for(int i=head[u];~i;i=e[i].next)
{
int v=e[i].v;
if(v==fa)continue;
dfs(v,u);
num[u]+=num[v];
}
ans=min(ans,Abs(sum-*num[u]));
}
int main()
{
int u,v,cas=;
while(scanf("%d%d",&n,&m)>)
{
if(n==&&m==)break;
tot=;
memset(head,-,sizeof(head));
sum=;
for(int i=;i<=n;i++)
scanf("%lld",&num[i]),sum+=num[i];
for(int i=;i<=m;i++)
{
scanf("%d%d",&u,&v);
addedge(u,v);
addedge(v,u);
}
ans=1LL<<;
dfs(,-);
printf("Case %d: %lld\n",cas++,ans);
}
}
上一篇:spring-data-rest的魔力 10分钟实现增删改查


下一篇:杀死你网站SEO的5个技术