zoukankan      html  css  js  c++  java
  • [dfs] Jzoj P1497 景点中心

    Description

    话说宁波市的中小学生在镇海中学参加计算机程序设计比赛,比赛之余,他们在镇海中学的各个景点参观。镇海中学共有n个景点,每个景点均有若干学生正在参观。这n个景点以自然数1至n编号,每两个景点的编号均不同。每两个景点之间有且只有一条路径。选择哪个景点集中的学生,才能使所有学生走过的路径之和最小呢?
     

    Input

    输入文件center.in中有若干行:
    第一行只有一个正整数n,表示景点数。
    第二行有n个1至1000间的整数,这n个整数间互相以一个空格分隔。其中第i个整数表示第i个景点处的学生数。
    第三行至第n+1行,每行有三个整数I,j,k,表示景点i和景点j之间有一条长尾k的路径直接连接。其中i<>j,1≤i≤n,1≤j≤n;1≤k≤1000。

    Output

    输出文件center.out中有二行;
    第一行只有一个整数i,表示在第i个景点处集中时,所有学生走过的路径之和最短。
    第二行也只有一个整数,表示所有学生走过的路径之和的最小值。
     

    Sample Input

    4
    3  2  4  1
    1  2  5
    3  1  6
    2  4  4
    

    Sample Output

    1
    43
    
     

    Hint






    【数据限制】
    所有的数据均随机生成,且满足:
    30%的数据,1≤n≤200。
    60%的数据,1≤n≤3000。
    100%的数据,1≤n≤100000。

    题解

    • 先可以定i为根,用dfs求出从i到根结点的价值和子树大小
    • 那么求完之后就可以求出所有点到i的距离
    • 设在A处集合时,所有人走的距离的和为B
    • 若C是A的儿子则所有人在C处集合的走的距离是C=B+(该边权值)*(总人数-2*size[C])

    代码

     1 #include<cstdio>
     2 #include<iostream>
     3 using namespace std;
     4 struct edge {int to,from,v; }e[100010*2];
     5 int head[100010],n,cnt=1;
     6 long long size[100010],dis[100010],mn,ans;
     7 void insert(int x,int y,int v) { e[cnt].to=y; e[cnt].v=v; e[cnt].from=head[x]; head[x]=cnt++; }
     8 void dfs(int x,int fa)
     9 {
    10     for (int i=head[x];i;i=e[i].from)
    11         if (e[i].to!=fa)
    12         {
    13             dfs(e[i].to,x);
    14             size[x]+=size[e[i].to];
    15             dis[x]+=dis[e[i].to]+size[e[i].to]*e[i].v;
    16         }
    17 }
    18 void dfs1(int x,int fa)
    19 {
    20     for (int i=head[x];i;i=e[i].from) 
    21         if (e[i].to!=fa)
    22         {
    23             dis[e[i].to]=dis[x]+e[i].v*(size[1]-2*size[e[i].to]);  
    24             dfs1(e[i].to,x);
    25         }
    26 }
    27 int main()    
    28 {
    29     scanf("%d",&n);
    30     for (int i=1;i<=n;i++) scanf("%lld",&size[i]);
    31     for (int i=1;i<=n-1;i++)
    32     {
    33         int x,y,v;
    34         scanf("%d%d%d",&x,&y,&v);
    35         insert(x,y,v); insert(y,x,v);
    36     }
    37     dfs(1,0);
    38     dfs1(1,0);
    39     mn=10000000000000;
    40     for (int i=1;i<=n;i++)
    41         if (mn>dis[i]) 
    42         {
    43             mn=dis[i];
    44             ans=i;
    45         }
    46     printf("%lld
    %lld",ans,mn);
    47     return 0;
    48 }
  • 相关阅读:
    Websphere 系列的https证书的配置说明
    Linux下运行windows程序
    Linux常见命令(三)
    使用Java语言开发微信公众平台(八)——自定义菜单功能
    Linux常见命令(二)
    微信小程序,前端大梦想(八)
    微信小程序,前端大梦想(七)
    使用Java语言开发微信公众平台(七)——音乐消息的回复
    微信小程序,前端大梦想(六)
    微信小程序,前端大梦想(五)
  • 原文地址:https://www.cnblogs.com/Comfortable/p/9277508.html
Copyright © 2011-2022 走看看