• 【模板】树的重心 洛谷P1364 医院设置


    P1364 医院设置

    题目描述

    设有一棵二叉树,如图:

                                             

    其中,圈中的数字表示结点中居民的人口。圈边上数字表示结点编号,现在要求在某个结点上建立一个医院,使所有居民所走的路程之和为最小,同时约定,相邻接点之间的距离为l。如上图中,

    若医院建在1 处,则距离和=4+12+2*20+2*40=136;若医院建在3 处,则距离和=4*2+13+20+40=81……

    输入输出格式

    输入格式:

    第一行一个整数n,表示树的结点数。(n≤100)

    接下来的n行每行描述了一个结点的状况,包含三个整数,整数之间用空格(一个或多个)分隔,其中:第一个数为居民人口数;第二个数为左链接,为0表示无链接;第三个数为右链接。

    输出格式:

    一个整数,表示最小距离和。

    输入输出样例

    输入样例#1:
    5						
    13 2 3
    4 0 0
    12 4 5
    20 0 0
    40 0 0
    
    输出样例#1:
    81
    【题解】
    随便找个跟DFS一下,第一个子树权值 * 2>=总权值的点即为重心(为什么?我也不知道)
    然后再DFS一下就好了
     1 #include <bits/stdc++.h>
     2 inline void read(int &x)
     3 {
     4     x = 0;char ch = getchar();char c = ch;
     5     while(ch > '9' || ch < '0')c = ch, ch = getchar();
     6     while(ch <= '9' && ch >= '0')x = x * 10 + ch - '0', ch = getchar();
     7     if(c == '-')x = -x;
     8 }
     9 
    10 const int INF = 0x3f3f3f3f;
    11 const int MAXN = 500 + 10;
    12 
    13 struct Edge
    14 {
    15     int u,v,next;
    16 }edge[MAXN + 1];
    17 int head[MAXN],cnt,root,b[MAXN],n,sum,w[MAXN],ans;
    18 
    19 void insert(int a, int b){edge[++cnt] = Edge{a,b,head[a]};head[a] = cnt;}
    20 
    21 int dfs1(int u)
    22 {
    23     register int tmp = w[u]; 
    24     for(register int pos = head[u];pos;pos = edge[pos].next)
    25     {
    26         int v = edge[pos].v;
    27         if(!b[v])
    28         {
    29             b[v] = true;
    30             tmp += dfs1(v);
    31             if(tmp * 2 >= sum && !root)
    32                 root = u;
    33             if(root)
    34                 return 0;
    35         }
    36     }
    37     return tmp;
    38 }
    39 
    40 void dfs2(int u, int step)
    41 {
    42     ans += w[u] * step;
    43     for(register int pos = head[u];pos;pos = edge[pos].next)
    44     {
    45         int v = edge[pos].v;
    46         if(!b[v])
    47         {
    48             b[v] = 1;
    49             dfs2(v, step + 1);
    50         }
    51     }
    52 }
    53 
    54 int main()
    55 {
    56     read(n);
    57     register int tmp1,tmp2,tmp3;
    58     for(register int i = 1;i <= n;++ i)
    59     {
    60         read(tmp1);read(tmp2);read(tmp3);
    61         if(tmp2)
    62             insert(i,tmp2),insert(tmp2,i);
    63         if(tmp3)
    64             insert(i,tmp3),insert(tmp3,i);
    65         w[i] = tmp1;
    66         sum += tmp1;
    67     }
    68     b[1] = 1;
    69     dfs1(1);
    70     memset(b, 0, sizeof(b));
    71     b[root] = 1;
    72     dfs2(root, 0);
    73     printf("%d", ans);
    74     return 0;
    75 }
    View Code
  • 相关阅读:
    Win2000下系统进程隐藏代码
    关于Windows下ShellCode编写的一点思考
    木马是如何编写的(三)
    MS04011远程缓冲区溢出代码
    关于Windows下ShellCode编写的一点思考
    木马是如何编写的(三)
    运用GIMP制作平面图片
    PCMan File Manager:标签式的文件解决软件
    AutoMySQLBackup——主动备份 MySQL 数据库的剧本
    ubuntu8.04下USB转UART接口的应用
  • 原文地址:https://www.cnblogs.com/huibixiaoxing/p/7118346.html
Copyright © 2020-2023  润新知