zoukankan      html  css  js  c++  java
  • 医院设置

    题目描述
    设有一棵二叉树,如图:

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

    复杂度O(n^2)

     1 #include<bits/stdc++.h>
     2 #define ll long long
     3 #define DB double
     4 using namespace std;
     5 const int N=1e6+10;
     6 struct node{
     7     int u,v,ne;
     8 }e[N];
     9 int h[N],tot,a[N],n;
    10 void add(int u,int v)
    11 {
    12     tot++;e[tot]=(node){u,v,h[u]};h[u]=tot;
    13 }
    14 ll ans,tmp;
    15 void dfs(int u,int fa,int d)
    16 {
    17     tmp+=1ll*a[u]*d;
    18     for(int i=h[u],rr;i;i=e[i].ne)
    19     {
    20         rr=e[i].v;
    21         if(rr!=fa) dfs(rr,u,d+1);
    22     }
    23 }
    24 int main()
    25 {
    26     scanf("%d",&n);
    27     for(int i=1,l,r;i<=n;++i)
    28     {
    29         scanf("%d",&a[i]);
    30         scanf("%d%d",&l,&r);
    31         if(l) add(i,l),add(l,i);
    32         if(r) add(i,r),add(r,i);
    33     }
    34     ans=1e12;
    35     for(int i=1;i<=n;++i)
    36     {
    37         tmp=0;
    38         dfs(i,0,0);
    39         ans=min(ans,tmp);
    40     }
    41     printf("%lld",ans);
    42     fclose(stdin);fclose(stdout);
    43     return 0;
    44 } 
    暴力

    也可以用树形DP来写,复杂度O(n)

    ok[i]表示以i为根的最优答案,首先我们预处理出ok[1]

    sz[i]表示i这棵子树的大小(节点数目之和)

    对于( u -> v ) 已知ok[u]

    我们只需要减去sz[v],加上除了sz[v]以外的节点数目

    即ok[v]=ok[u]-sz[v]+sz[1]-sz[v]=ok[u]+sz[1]-2*sz[v]

    得解。

     1 #include<bits/stdc++.h>
     2 #define ll long long
     3 #define DB double
     4 using namespace std;
     5 const int N=1e4+10;
     6 struct node{
     7     int u,v,ne;
     8 }e[N];
     9 int h[N],tot,a[N],n,sz[N];
    10 void add(int u,int v)
    11 {
    12     tot++;e[tot]=(node){u,v,h[u]};h[u]=tot;
    13 }
    14 ll ans,tmp,ok[N];
    15 void dfs1(int u,int fa,int d)
    16 {
    17     ans+=1ll*a[u]*d;
    18     for(int i=h[u],rr;i;i=e[i].ne)
    19     {
    20         rr=e[i].v;
    21         if(rr!=fa) dfs1(rr,u,d+1),sz[u]+=sz[rr];
    22     }
    23 }
    24 void dfs2(int u,int fa)
    25 {
    26     ans=min(ans,ok[u]);
    27     for(int i=h[u],rr;i;i=e[i].ne)
    28     {
    29         rr=e[i].v;
    30         if(rr!=fa) 
    31         {
    32             ok[rr]=ok[u]+sz[1]-2*sz[rr];
    33             dfs2(rr,u);
    34         }
    35     }
    36 }
    37 int main()
    38 {
    39     scanf("%d",&n);
    40     for(int i=1,l,r;i<=n;++i)
    41     {
    42         scanf("%d",&a[i]);sz[i]=a[i];
    43         scanf("%d%d",&l,&r);
    44         if(l) add(i,l),add(l,i);
    45         if(r) add(i,r),add(r,i);
    46     }
    47     dfs1(1,0,0);ok[1]=ans;
    48     dfs2(1,0); 
    49     printf("%lld",ans);
    50     fclose(stdin);fclose(stdout);
    51     return 0;
    52 } 
    树形DP
  • 相关阅读:
    常用日期函数介绍
    常用数学函数介绍
    oracle 常用sql字符函数介绍
    centos6.5 相关命令
    Kettle5.4.0 java.lang.OutOfMemoryError
    oracle多表连接方式Hash Join Nested Loop Join Merge Join
    CONNECT_BY_ROOT
    设置Oracle PL/SQL时间显示格式NLS_TIMESTAMP_FORMAT
    INSTR代替NOT LIKE
    多表插入
  • 原文地址:https://www.cnblogs.com/adelalove/p/8848791.html
Copyright © 2011-2022 走看看