P1364 医院设置

题意:给出一棵树,每个节点有权值,让我们确定在哪个地方安装医院,距离最短?

    何为距离?你猜

思路:这道题给出的n的范围只有100,所以很明显我们可以直接暴力n^2搜答案,这可以过

代码如下

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 const int maxn=1e2+10;
 4 const int inf=0x3f3f3f3f;
 5 int a[maxn];
 6 struct node
 7 {
 8     int v,nxt;
 9 }G[maxn<<1];
10 int head[maxn];int num;
11 void add(int u,int v)
12 {
13     G[++num].v=v;G[num].nxt=head[u];head[u]=num;
14 }
15 int ans=inf;
16 int sum=0;
17 void dfs(int u,int fa,int step)
18 {
19     sum+=a[u]*step;
20     for(int i=head[u];i;i=G[i].nxt){
21         int v=G[i].v;
22         if(v==fa) continue;
23         dfs(v,u,step+1);
24     }
25 }
26 int main()
27 {
28     int n;
29     scanf("%d",&n);
30     for(int i=1;i<=n;i++){
31         int w,u,v;
32         scanf("%d%d%d",&w,&u,&v);
33         a[i]=w;
34         if(u) add(i,u),add(u,i);
35         if(v) add(i,v),add(v,i);
36     }
37     for(int i=1;i<=n;i++){
38         sum=0;
39         dfs(i,0,0);
40         ans=min(ans,sum);
41     }
42     printf("%d\n",ans);
43     return 0;
44 }
View Code

  但是:假如n的范围是1e5呢,就过不去了

  所以我们可以用树的重心来解决这道题

    树的重心有以下性质:

      1、树上所有的点到树的重心的距离之和是最短的,如果有多个重心,那么总距离相等。

      2、插入或删除一个点,树的重心的位置最多移动一个单位。

      3、若添加一条边连接2棵树,那么新树的重心一定在原来两棵树的重心的路径上。

    我们只需要用到第一条性质,将题目中给出的节点权值转化为节点个数就跟树的重心一模一样了

       然后,求出哪个位置为重心后,我们就再枚举一遍即可

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 const int maxn=1e2+10;
 4 const int inf=0x3f3f3f3f;
 5 int a[maxn];
 6 struct node
 7 {
 8     int v,nxt;
 9 }G[maxn<<1];
10 int head[maxn];int num;
11 void add(int u,int v)
12 {
13     G[++num].v=v;G[num].nxt=head[u];head[u]=num;
14 }
15 int ans=inf;
16 int sum;
17 int mxnode=0;
18 int mxnum=inf;
19 int siz[maxn];
20 void dfs(int u,int fa,int step)
21 {
22     siz[u]=a[u];
23     int tmp=0;
24     for(int i=head[u];i;i=G[i].nxt){
25         int v=G[i].v;
26         if(v==fa) continue;
27         dfs(v,u,step+1);
28         siz[u]+=siz[v];
29         tmp=max(tmp,siz[v]);
30     }
31     tmp=max(tmp,sum-siz[u]);
32     if(mxnum>tmp){
33         mxnum=tmp;
34         mxnode=u;
35     }
36 }
37 void dfs1(int u,int fa,int step)
38 {
39     sum+=a[u]*step;
40     for(int i=head[u];i;i=G[i].nxt){
41         int v=G[i].v;
42         if(v==fa) continue;
43         dfs1(v,u,step+1);
44     }
45 }
46 int main()
47 {
48     int n;
49     scanf("%d",&n);
50     for(int i=1;i<=n;i++){
51         int w,u,v;
52         scanf("%d%d%d",&w,&u,&v);
53         a[i]=w;
54         sum+=w;
55         if(u) add(i,u),add(u,i);
56         if(v) add(i,v),add(v,i);
57     }
58     dfs(1,0,0);
59     //printf("%d\n",mxnode);
60     sum=0;
61     dfs1(mxnode,0,0);
62     printf("%d\n",sum);
63     return 0;
64 }
View Code

 

posted @ 2020-03-31 13:02  古比  阅读(197)  评论(0编辑  收藏  举报