[HDU3899]JLUCPC

Time Limit: 15000/5000 MS (Java/Others)
Memory Limit: 65536/65536 K (Java/Others)

Problem Description
Dr. Skywind and Dr. Walkoncloud are planning to hold the annual JLU Collegiate Programming Contest. The contest was always held in the college of software in the past. However, they changed their minds and decided to find the most convenient location from all colleges this year.
Each college in JLU is located in one of the N ( 1 &lt; = N &lt; = 100 , 000 ) N (1 &lt;= N &lt;= 100,000) N(1<=N<=100,000) different locations (labeled as 1 1 1 to N N N) connected by N − 1 N-1 N1 roads. Any two colleges are reachable to each other. The Contest can be held at any one of these N colleges. Moreover, Road i connects college A i A_i Ai and B i B_i Bi ( 1 &lt; = A i &lt; = N ; 1 &lt; = B i &lt; = N ) (1 &lt;= A_i &lt;=N; 1 &lt;= B_i &lt;= N) (1<=Ai<=N;1<=Bi<=N) and has length L i ( 1 &lt; = L i &lt; = 1 , 000 ) L_i (1 &lt;= L_i &lt;= 1,000) Li(1<=Li<=1,000). College i i i has T i ( 0 &lt; = T i &lt; = 1 , 000 ) T_i (0 &lt;= T_i &lt;= 1,000) Ti(0<=Ti<=1,000) teams participating in the contest.
When choosing the college to hold the Contest, Dr. Skywind wishes to minimize the inconvenience of the chosen location. The inconvenience of choosing college P P P is the sum of the distance that all teams need to reach college P P P (i.e., if the distance from college i i i to college P P P is 20 20 20, then the travel distance is T i T_i Ti* 20 20 20). Please help Dr. Skywind and Dr. Walkoncloud to choose the most convenient location for the contest.

Input
There are multiple test cases. For each case, the first line contains a single integer N N N, indicating the number of colleges. The next N N N lines describes T 1 T_1 T1 to T n T_n Tn. Then, each of the last N − 1 N-1 N1 lines will contain 3 3 3 integers, namely A i A_i Ai, B i B_i Bi and L i L_i Li.

Output
For each case, output the minimum inconvenience possible

Sample Input

3
1
1
2
1 2 2
2 3 1
4
100
1
1
1
1 2 1
2 3 1
2 4 1

Sample Output

4
5

Source
2011 Multi-University Training Contest 6 - Host by JLU

题意:
n n n个学校要举办比赛,这 n n n所学校之间的路径构成一棵树,第 i i i个学校派出 T [ i ] T[i] T[i]个队,求选定一个学校作为比赛举办地点,使得 ∑ ( T [ i ] ∗ d i s [ i ] ) \sum(T[i]*dis[i]) (T[i]dis[i])最小, d i s [ i ] dis[i] dis[i]为第 i i i所学校到比赛举办地点的距离。

题解:
两次dfs
我们先假设学校1为举办地点,求出答案,设 e c p [ i ] ecp[i] ecp[i]为如果 i i i点是举办地点,以 i i i为根节点的子树的答案是多少;设 s z [ i ] sz[i] sz[i]为以 i i i为根节点的子树的队伍的数量。很显然 e c p [ 1 ] ecp[1] ecp[1]就是以 1 1 1为举办地点所对应的答案。考虑答案向子树转移的代价,如果举办地点从 a a a转移到与 a a a相邻的 b b b,设在 a a a的时候答案是 a n s ans ans,那么到b的时候答案就是 a n s − s z [ b ] ∗ w ( a , b ) + ( s u m − s z [ b ] ) ∗ w ( a , b ) ans-sz[b]*w(a,b)+(sum-sz[b])*w(a,b) anssz[b]w(a,b)+(sumsz[b])w(a,b) w ( a , b ) w(a,b) w(a,b) ( a , b ) (a,b) (a,b)这条边的长度, s u m sum sum表示所有参赛队伍的数量。 b b b点所在子树的所有队伍都可以不用走 ( a , b ) (a,b) (a,b)这条边了,所以减去 s z [ b ] ∗ w ( a , b ) sz[b]*w(a,b) sz[b]w(a,b),所有除了 b b b子树上的队伍都要走 ( a , b ) (a,b) (a,b)这条边,所以答案加上 ( s u m − s z [ b ] ) ∗ w ( a , b ) (sum-sz[b])*w(a,b) (sumsz[b])w(a,b),化简一下式子就是 a n s + ( s u m − 2 ∗ s z [ b ] ) ∗ w ( a , b ) ans+(sum-2*sz[b])*w(a,b) ans+(sum2sz[b])w(a,b)
第一遍dfs求ecp,然后第二遍求最小的ans就行了。可能会炸int,所以请用long long

#include<bits/stdc++.h>
#define LiangJiaJun main
#define ll long long
using namespace std;
int a[100004],n;
int ne,h[100004];
ll ecp[100004],sz[100004],ans,sum;
bool vis[100004];
struct edge{
    int to,nt,w;
}e[400004];
void add(int u,int v,int w){
     e[++ne].to=v;e[ne].w=w;e[ne].nt=h[u];
     h[u]=ne;
}
void dfs(int x){
     vis[x]=1;
     sz[x]=a[x];
     ecp[x]=0;
     for(int i=h[x];i;i=e[i].nt){
         if(vis[e[i].to])continue;
         dfs(e[i].to);
         sz[x]+=sz[e[i].to];
         ecp[x]+=ecp[e[i].to]+sz[e[i].to]*e[i].w;
     }
}
void calc(int x,ll val){
     ans=min(ans,val);
     vis[x]=1;
     for(int i=h[x];i;i=e[i].nt){
        if(vis[e[i].to])continue;
        ll nxt_val=val+(sum-2LL*sz[e[i].to])*e[i].w;
        calc(e[i].to,nxt_val);
     }
}
int w33ha(){
    ne=0;
    memset(h,0,sizeof(h));
    for(int i=1;i<=n;i++)vis[i]=0;
    for(int i=1;i<=n;i++)scanf("%d",&a[i]);
    for(int i=1;i<n;i++){
        int u,v,w;
        scanf("%d%d%d",&u,&v,&w);
        add(u,v,w);
        add(v,u,w);
    }
    dfs(1);
    ans=ecp[1];
    sum=sz[1];
    for(int i=1;i<=n;i++)vis[i]=0;
    calc(1,ans);
    printf("%lld\n",ans);
    return 0;
}
int LiangJiaJun(){
    while(scanf("%d",&n)!=EOF)w33ha();
    return 0;
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值