[关键字]:Bfs
[题目大意]:http://221.192.240.123:8586/JudgeOnline/showproblem?problem_id=1670
//=====================================================================================================
[分析]:其实很水,因为树都已经给出只要任选一个根建树,记录以每个点位根的子树有多少节点,每条边的费用就是a[i].d*abs((N-f[i].d)-f[i].d)f[i].d是以i为根的子树的节点数a[i].d是边的长度。因为N很大,所以递规建树会爆栈,所以先记录下BFS序,此时从后往前找就是从叶往根找,用当前节点更新父节点。
[代码]:
View Code
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
#define MAXN 1005000
struct node
{
int x,y,d,n;
}e[MAXN*2],a[MAXN];
struct rec
{
int f,d;
}f[MAXN];
int N,tot;
int first[MAXN],q[MAXN];
long long ans=0;
bool b[MAXN];
void make(int x,int y,int z)
{
e[++tot].y=y;
e[tot].x=x;
e[tot].d=z;
e[tot].n=first[x];
first[x]=tot;
}
void Build()
{
int head=0,tail=0;
memset(q,0,sizeof(q));
memset(b,0,sizeof(b));
q[++tail]=1;
f[1].f=0;
f[1].d=1;
b[1]=1;
while (head<tail)
{
head++;
for (int i=first[q[head]];i;i=e[i].n)
if (!b[e[i].y])
{
q[++tail]=e[i].y;
b[e[i].y]=1;
f[e[i].y].f=q[head];
f[e[i].y].d=1;
}
}
//printf("%d %d %d\n",head,tail,tot);
//for (int i=1;i<=tail;i++) printf("%d ",q[i]);printf("\n");
for (int i=tail;i>=1;i--) f[f[q[i]].f].d+=f[q[i]].d;
//for (int i=1;i<=N;i++) printf("%d %d %d\n",i,f[i].d,f[i].f);
}
int main()
{
freopen("in.txt","r",stdin);
freopen("out.txt","w",stdout);
scanf("%d",&N);
int x,y,z;
for (int i=1;i<N;i++)
{
scanf("%d%d%d",&x,&y,&z);
a[i].x=x,a[i].y=y,a[i].d=z;
make(x,y,z);
make(y,x,z);
}
//for (int i=1;i<=tot;i++) printf("%d %d\n",e[i].y,e[i].d);
Build();
for (int i=1;i<N;i++)
{
if (f[a[i].x].f==a[i].y) ans+=(long long) a[i].d*abs(N-f[a[i].x].d-f[a[i].x].d);
if (f[a[i].y].f==a[i].x) ans+=(long long) a[i].d*abs(N-f[a[i].y].d-f[a[i].y].d);
//printf("%lld\n",ans);
}
printf("%lld\n",ans);
return 0;
}