Link:http://acdream.info/contest?cid=1374#problem-C
C - 哗啦啦村的扩建
Time Limit:
2000/1000MS (Java/Others)
Memory Limit:
512000/256000KB (Java/Others)
Problem Description
呀呀呀,哗啦啦村在日渐发展中,越来越大了。
唐老师看到这欣欣向荣的情景,感到非常开心。
狗哥在旁边,“喏,我们村子扩建这么快,肯定用了不少钱吧?”
唐老师说:“是呀,不过这些钱都不及我零花钱的万万分之一。”
那么这时候问题来了,唐老师的零花钱至少应该有多少钱呢?
狗哥也想知道这道题的答案,于是他拜托了青君同学,了解到了村子扩建的费用。
啊,原来村子的扩建费用,就是修建道路的费用。
整个村子可以看作有n个房子,村子会修建n-1条道路,保证从任意房子可以到达任意其他房子。
那修建这n-1条道路的费用怎么记呢?对于每条道路,假设这条道路左边有x个房子,右边有y个房子,这条道路长度为k,那么费用就是k*|x-y|。
那么唐老师的零花钱至少有多少钱呢?现在你应该知道了吧。
Input
第一行一个整数,表示这个村子有n个房子
接下来n-1行,表示每条道路的信息,三个整数 a,b,c,表示a,b之间有一条道路,这条路的长度为c
1<=n<=50,000
1≤ai, bi≤n
0 ≤ci≤ 10^6
Output
输出一个整数,表示唐老师的零花钱至少有多少钱
Sample Input
6 1 2 1 1 3 1 1 4 2 6 3 1 5 2 1
Sample Output
2000000000
坑点:见代码注释部分。
AC code:
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cmath>
#include<cstring>
#define MAXN 1000010
#define LL long long
using namespace std;
struct node{
int v;
int next;
LL w;//只能用long long
}edge[MAXN];
int head[MAXN];
int fg[MAXN];
int cnt[MAXN];
int n,tot;
int dp[MAXN];
LL ans=0;
void add(int from,int to,int w)
{
edge[tot].w=w;
edge[tot].v=to;
edge[tot].next=head[from];
head[from]=tot++;
}
void dfs(int p)
{
fg[p]=1;//因为无向图边是双向的,为避免重复走,走过的点必须做标记
for(int i=head[p];i!=0;i=edge[i].next)
{
int v=edge[i].v;
if(fg[v]==1)// 走过的点
continue;
else
{
dfs(v);
cnt[p]+=cnt[v];
edge[i].w=edge[i].w*abs(n-2*cnt[v]);
ans+=edge[i].w;
}
}
}
int main()
{
int u,v,w;
//freopen("D:\in.txt","r",stdin);
while(scanf("%d",&n)!=EOF)
{
for(int i=1;i<=n;i++)//注意:memset函数只能初始化数组为0或-1,
{ //初始化其他数只能用for循环
cnt[i]=1;
}
memset(head,0,sizeof(head));
memset(fg,0,sizeof(fg));
//memset(cnt,1,sizeof(cnt));
//printf("%d\n",cnt[2]);
tot=1;
int t=n-1;
while(t--)
{
scanf("%d%d%d",&u,&v,&w);
add(u,v,w);
add(v,u,w);
}
ans=0;
dfs(1);
// printf("%lld\n",ans*100000000);//不能这样写,会爆LL!
if(ans!=0)
printf("%lld00000000\n",ans);
else
{
printf("0\n");
}
}
return 0;
}