1497. 景点中心

Description

话说宁波市的中小学生在镇海中学参加计算机程序设计比赛,比赛之余,他们在镇海中学的各个景点参观。镇海中学共有n个景点,每个景点均有若干学生正在参观。这n个景点以自然数1至n编号,每两个景点的编号均不同。每两个景点之间有且只有一条路径。选择哪个景点集中的学生,才能使所有学生走过的路径之和最小呢?
如果存在多个解,则输出距离1最近的那个点,可以证明答案唯一

Input

输入文件center.in中有若干行:
第一行只有一个正整数n,表示景点数。
第二行有n个1至1000间的整数,这n个整数间互相以一个空格分隔。其中第i个整数表示第i个景点处的学生数。
第三行至第n+1行,每行有三个整数I,j,k,表示景点i和景点j之间有一条长尾k的路径直接连接。其中i<>j,1≤i≤n,1≤j≤n;1≤k≤1000。

Output

输出文件center.out中有二行;
第一行只有一个整数i,表示在第i个景点处集中时,所有学生走过的路径之和最短。
第二行也只有一个整数,表示所有学生走过的路径之和的最小值。

Sample Input

4
3 2 4 1
1 2 5
3 1 6
2 4 4

Sample Output

1
43

Data Constraint

Hint






【数据限制】
所有的数据均随机生成,且满足:
30%的数据,1≤n≤200。
60%的数据,1≤n≤3000。
100%的数据,1≤n≤100000。

Solution

树形dp,然后换一下根即可。

Code

#include<cstdio> 
#include<cstring>
#include<algorithm>
#define I int
#define ll long long
#define son t[k]
#define F(i,a,b) for(I i=a;i<=b;i++)
#define N 100005
using namespace std;
I n,m,x,y,z,tot,t[N<<1],nx[N<<1],ls[N],now;
ll ans=1ll<<55,w[N<<1],f[N],sz[N],sum;
char c;
void R(I &x){
	I p=1;x=0;c=getchar();
	while(c<'0'||c>'9'){if(c=='-') p=-1;c=getchar();}
	while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
	x*=p;
}
void add(I x,I y,I z){
	t[++tot]=y,nx[tot]=ls[x],ls[x]=tot,w[tot]=z;
}
void dg(I x,I y){
	for(I k=ls[x];k;k=nx[k]) if(son!=y){
		dg(son,x);
		sz[x]+=sz[son];
		f[x]+=f[son]+sz[son]*w[k];
	}
}
void get(I x,I y){
	if(f[x]<ans){ans=f[x],now=x;}
	for(I k=ls[x];k;k=nx[k]) if(son!=y){
		f[son]=f[x]+(sum-sz[son])*w[k]-sz[son]*w[k];
		get(son,x);
	}
}
I main(){
	R(n);
	F(i,1,n) R(x),sum+=(sz[i]=x);
	F(i,1,n-1){
		R(x),R(y),R(z);
		add(x,y,z),add(y,x,z);
	}
	dg(1,0);
	get(1,0);
	printf("%d\n%lld\n",now,ans);
	return 0;
}

猜你喜欢

转载自blog.csdn.net/zsjzliziyang/article/details/107943471