题目描述
The architectural structure of the college is strange, but the rule is that there is only one simple path between every two classrooms. Now the battle between Class A and Class F broke out. As a support staff of Class F, you have to go to every fight in time to help out. With the help of icebound, Class F know the probability of each classroom being attacked. So we define an important degree for each classroom. Now ask you to find a classroom x in n classrooms as your resting base which has the minimum F(x). F(x) = ∑ w(i) × d(x, i), d is the distance between x and i.
输入
he first line is an integer n,which is the number of classrooms.
Then n-1 lines follow. Each line has three numbers x,y,z. There is a road of z meters between x and y.
The last line contains n numbers. The i‑th number w(i) is the important degree of the classroom.
2 ≤ n ≤ 5 × 105, 0 ≤ z, wi ≤ 1000,1 ≤ x, y ≤ n
输出
Output a line with an integer, representing the minimum F(x).
样例输入 Copy
5 1 2 1 2 3 1 2 4 1 3 5 6 2 3 1 8 7
样例输出 Copy
60
题意:给了n个点任意两个点之间只有直接或间接一条边进行相连。每一个点都有一个权值,想让找到一个x点,使得F(x)最小. F(x) = ∑ w(i) × d(x, i), (wi为第i个点的权值,d(x,i)从第x个点到第i个点的距离)
思路:我们可以先根据一个点求出所有的距离,以及这个点的f(x).然后在通过转换起点,来寻找最小值。
第一图:如果我们从一号点开始找,那么我们的f(x)=(w2+w3+w4+w5)*d1 + (w3+w5)*d2 + (w4)*d3 + w5*d4;
所以我们在第一查找的时候,直接更新每一个点的权值,其权值+=后面所有点的权值和。
第二个图:我们现在已经知道了一个f(x)并且每一个点的权值也更新了,现在假设起点是p,我想要把起点转换到q点上,只需要把两点权值更新即可。那么我怎样来算总和呢?
首先已知 sum = ... + q*d 那么现在我起点换成q这个点了 sum - q*d + (p-q)*d (从q点到p点以后所有点要用到d的和 )
此时问题就解决了,切记,不管是哪种情况,只需要对每一个点进行一次操作即可。
代码如下:
#include<bits/stdc++.h>
#define ll long long
#define N 1000010
using namespace std;
int k,a[N],u[N],v[N],w[N],first[N],Next[N],book[N];
ll minn;
void init(int x)
{
Next[k]=first[u[x]];
first[u[x]]=k;
k++;
}
ll dfs1(int x,int len)
{
ll sum=0;
for(int i=first[x]; i!=-1; i=Next[i])
{
if(book[v[i]])continue;
book[v[i]]=1;
sum+=dfs1(v[i],w[i]);
a[x]+=a[v[i]];
}
sum+=(ll)a[x]*len;
return sum;
}
void dfs2(int x,ll sum)
{
minn=min(minn,sum);
for(int i=first[x]; i!=-1; i=Next[i])
{
if(book[v[i]])continue;
book[v[i]]=1;
int p=a[x];
int q=a[v[i]];
a[x]=p-q;
a[v[i]]=p;
dfs2(v[i],sum+(ll)(p-2*q)*w[i]);
a[x]=p;
a[v[i]]=q;
}
}
int main()
{
int n;
memset(first,-1,sizeof(first));
scanf("%d",&n);
k=1;
for(int i=1; i<n; i++)
{
scanf("%d%d%d",&u[i],&v[i],&w[i]);
u[i+n-1]=v[i];
v[i+n-1]=u[i];
w[i+n-1]=w[i];
}
for(int i=1;i<=2*n-2;i++)
init(i);
for(int i=1; i<=n; i++)
scanf("%d",&a[i]);
memset(book,0,sizeof(book));
book[1]=1;
ll sum=dfs1(1,0);
memset(book,0,sizeof(book));
minn=sum;
book[1]=1;
dfs2(1,sum);
printf("%lld\n",minn);
return 0;
}