• 洛谷P1395 会议(CODEVS.3029.设置位置)(求树的重心)


    To 洛谷.1395 会议 To CODEVS.3029 设置位置

    题目描述

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

    输入输出格式

    输入格式:

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

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

    输出格式:

    一行输出两个数字x和y

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

    y表示距离之和的最小值

    输入输出样例

    输入样例#1:
    4
    1 2 
    2 3 
    3 4 
    
    输出样例#1:
    2 4

    说明

    【数据范围】

    70%数据n<=1000

    100%数据n<=50000

    思路:

      求树的重心,然后求重心到每个点的距离。(树的重心 百度百科

      如果用n遍spfa会超时。

    代码:

    1.dfs

     1 #include<cmath>
     2 #include<cstdio>
     3 #include<algorithm>
     4 using namespace std;
     5 const int N=50005,INF=0x3f3f3f3f;
     6 
     7 int n,cnt,Ans,Min,size=INF,H[N<<1],son[N],dep[N];
     8 bool vis[N];
     9 struct Edge
    10 {
    11     int to,nxt;
    12 }e[N<<1];
    13 
    14 void read(int &now)
    15 {
    16     now=0;bool f=0;char c=getchar();
    17     while(c>'9'||c<'0')
    18     {
    19         if(c=='-')f=1;
    20         c=getchar();
    21     }
    22     while(c>='0'&&c<='9')now=(now<<3)+(now<<1)+c-'0',c=getchar();
    23     now= f?-now:now;
    24 }
    25 
    26 void AddEdge(int u,int v)
    27 {
    28     e[++cnt].to = v;
    29     e[cnt].nxt = H[u];
    30     H[u] = cnt;
    31 }
    32 
    33 void DFS(int cur)
    34 {//求树的重心 
    35     vis[cur]=1;
    36     son[cur]=0;
    37     int tmp=0;
    38     for(int i=H[cur];i;i=e[i].nxt)
    39     {
    40         if(!vis[e[i].to])
    41         {
    42             DFS(e[i].to);
    43             son[cur]+=son[e[i].to]+1;
    44             tmp=max(tmp,son[e[i].to]+1);
    45         }
    46     }
    47     tmp=max(tmp,n-son[cur]-1);
    48     if(size>tmp || tmp==size&&Ans>cur)
    49     {
    50         Ans=cur;
    51         size=tmp;
    52     }
    53 }
    54 
    55 void DFSforDeep(int x,int y,int d)
    56 {
    57     dep[x]=d;
    58     for(int i=H[x];i;i=e[i].nxt)
    59       if(y != e[i].to)
    60         DFSforDeep(e[i].to,x,d+1);
    61 }
    62 
    63 int main()
    64 {
    65     read(n);
    66     int x,y;
    67     for(int i=1;i<n;++i)
    68     {
    69         read(x);read(y);
    70         AddEdge(x,y);
    71         AddEdge(y,x);
    72     }
    73     DFS(1);
    74     DFSforDeep(Ans,Ans,0);
    75     for(int i=1;i<=n;++i)
    76       Min+=abs(dep[Ans]-dep[i]);
    77     printf("%d %d",Ans,Min);    
    78     return 0;
    79 }
    AC

    2.70分的spfa

     1 #include<queue>
     2 #include<cstdio>
     3 using namespace std;
     4 const int N=50005,INF=0x3f3f3f3f;
     5 
     6 int n,cnt,Ans,Min=INF,H[N<<1],Dist[N];
     7 bool Exist[N];
     8 queue<int>q;
     9 struct Edge
    10 {
    11     int to,nxt;
    12 }e[N<<1];
    13 
    14 void read(int &now)
    15 {
    16     now=0;bool f=0;char c=getchar();
    17     while(c>'9'||c<'0')
    18     {
    19         if(c=='-')f=1;
    20         c=getchar();
    21     }
    22     while(c>='0'&&c<='9')now=(now<<3)+(now<<1)+c-'0',c=getchar();
    23     now= f?-now:now;
    24 }
    25 
    26 void AddEdge(int u,int v)
    27 {
    28     e[++cnt].to = v;
    29     e[cnt].nxt = H[u];
    30     H[u] = cnt;
    31 }
    32 
    33 void spfa(int x)
    34 {
    35     for(int i=1;i<=n;++i)
    36       Exist[i]=0,Dist[i]=INF;
    37     Dist[x]=0;
    38     Exist[x]=1;
    39     q.push(x);
    40     while(!q.empty())
    41     {
    42         int cur=q.front();
    43         q.pop();
    44         Exist[cur]=0;
    45         for(int i=H[cur];i;i=e[i].nxt)
    46         {
    47             int to=e[i].to;
    48             if(Dist[to]<=Dist[cur]+1)continue;
    49             Dist[to]=Dist[cur]+1;
    50             if(!Exist[to])
    51               q.push(to),Exist[to]=1;
    52         }
    53     }
    54 }
    55 
    56 int main()
    57 {
    58     read(n);
    59     int x,y;
    60     for(int i=1;i<n;++i)
    61     {
    62         read(x);read(y);
    63         AddEdge(x,y);
    64         AddEdge(y,x);
    65     }
    66     for(int i=1;i<=n;++i)
    67     {
    68         spfa(i);
    69         int sum=0;bool OK=1;
    70         for(int j=1;j<=n;++j)
    71           if(Dist[j]==INF)
    72           {
    73                 OK=0;break;//防止累加INF溢出,不知道有没有用 
    74           }
    75           else
    76             sum+=Dist[j];
    77         if(sum<Min && OK)
    78           Min=sum,Ans=i;
    79     }
    80     printf("%d %d",Ans,Min);    
    81     return 0;
    82 }
    TLE
  • 相关阅读:
    [转] 面向对象软件开发和过程(六)针对契约设计
    [转] 面向对象软件开发和过程(三)案例实战(下)
    条形码字体下载
    [转] 面向对象软件开发和过程(五)优化代码的组织
    JQuery动画效果
    实时监听文本框状态的方法
    JQuery操作元素的属性与样式及位置
    AJAX XMLHttpRequest对象
    JQuery常用方法技巧
    CSS弹出二级菜单
  • 原文地址:https://www.cnblogs.com/SovietPower/p/6897901.html
Copyright © 2020-2023  润新知