• luogu 1395 会议


    题目描述

    有一个村庄居住着 nn 个村民,有 n-1n1 条路径使得这 nn 个村民的家联通,每条路径的长度都为 11。现在村长希望在某个村民家中召开一场会议,村长希望所有村民到会议地点的距离之和最小,那么村长应该要把会议地点设置在哪个村民的家中,并且这个距离总和最小是多少?若有多个节点都满足条件,则选择节点编号最小的那个点。

    输入格式

    第一行,一个数 nn,表示有 nn 个村民。

    接下来 n-1n1 行,每行两个数字 aa 和 bb,表示村民 aa 的家和村民 bb 的家之间存在一条路径。

    输出格式

    一行输出两个数字 xx 和 yy。

    xx 表示村长将会在哪个村民家中举办会议。

    yy 表示距离之和的最小值。

    输入输出样例

    输入 #1
    4
    1 2 
    2 3 
    3 4 
    
    输出 #1
    2 4

    说明/提示

    数据范围

    对于 70\%70% 数据 n le 10^3n103。

    对于 100\%100% 数据 n le 5 imes 10^4n5×104。

    ————————————————————————————

    简单的树形DP

    f[i]:i点为根的子树中所有节点到i点集中的路径总长度

    cnt[i]:i点的子树内的节点数

    f[i]=sum(f[son]+cnt[son])

    ff[i]:表示i点集中的路径长度之和

    ff[i]=ff[fa]+n-cnt[i]*2

    ff[i]=f[i]+(ff[fa]-f[i]-cnt[[i])+(n-cnt[i])

    上式中,f[i]孩子们在i点集中的路径长度

    第一个()内为除了i点外的所有节点在fa集中的路径长度综合

    第二个()内为fa点到i点的边要有这么多的点从这条边上向i点集中

    ————————————————————————————

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 const int maxn=5e4+10;
     4 int n;
     5 struct edge
     6 {
     7     int u,v,nxt;
     8 }e[maxn<<1];
     9 int head[maxn],js;
    10 void addage(int u,int v)
    11 {
    12     e[++js].u=u;e[js].v=v;
    13     e[js].nxt=head[u];head[u]=js;
    14 }
    15 int f[maxn],cnt[maxn],ff[maxn];
    16 void dfs(int u,int fa)
    17 {
    18     cnt[u]=1;f[u]=0;
    19     for(int i=head[u];i;i=e[i].nxt)
    20     {
    21         int v=e[i].v;
    22         if(v==fa)continue;
    23         dfs(v,u);
    24         cnt[u]+=cnt[v];
    25         f[u]+=f[v]+cnt[v];
    26     }
    27 }
    28 void dfss(int u,int fa)
    29 {
    30     if(fa)ff[u]=ff[fa]+n-cnt[u]-cnt[u];
    31     for(int i=head[u];i;i=e[i].nxt)
    32     {
    33         int v=e[i].v;
    34         if(v!=fa)dfss(v,u);
    35     }
    36 }
    37 int main()
    38 {
    39     scanf("%d",&n);
    40     for(int u,v,i=1;i<n;++i)
    41     {
    42         scanf("%d%d",&u,&v);
    43         addage(u,v);addage(v,u);
    44     }
    45     dfs(1,0);
    46     ff[1]=f[1];
    47     dfss(1,0);
    48     int mx=ff[1],mxn=1;;
    49     for(int i=2;i<=n;++i)
    50     {
    51         if(ff[i]<mx)mx=ff[i],mxn=i;
    52     }
    53     printf("%d %d",mxn,mx);
    54     return 0;
    55 }
    View Code
  • 相关阅读:
    程序员面试中有几大法则
    实现立方体旋转
    为什么技术与产品沟通起来总是那么痛苦
    移动互联网下半场的面试真经,让你进入 BAT 不再是梦
    Javascript+H5实现打小地鼠游戏
    Python多进程应用
    Python数据分析笔记:聚类算法之K均值
    给新手程序员的16个工作必备小妙招,省下时间去LOL吧!
    MySQL数据库开发常见问题及优化
    java中的四种引用类型
  • 原文地址:https://www.cnblogs.com/gryzy/p/14584828.html
Copyright © 2020-2023  润新知