zoukankan      html  css  js  c++  java
  • 树的重心

    树的重心:对于一棵n个结点的无根树,找到一个点,使得把树变成以该点为根的有根树树时,最大子树的结点数最小。关于重心的求法见《算法竞赛入门经典第二版》281页

    下面来看两个基础的题目:

    链接

    分析:求出树的重心以及最大子树的结点数

     1 #include "iostream"
     2 #include "cstdio"
     3 #include "cstring"
     4 #include "string"
     5 #include "vector"
     6 using namespace std;
     7 const int maxn=20000+10;
     8 const int INF=1<<30;
     9 int T,n;
    10 vector<int> g[maxn];
    11 int wide[maxn],f[maxn],dp[maxn],son[maxn];
    12 int wide_max;
    13 void init(){
    14     scanf("%d",&n);
    15     for(int i=0;i<=n;i++)
    16         g[i].clear();
    17     for(int i=1;i<n;i++){
    18         int x,y;
    19         scanf("%d%d",&x,&y);
    20         g[x].push_back(y);
    21         g[y].push_back(x);
    22     }
    23 }
    24 void dfs(int v,int fa){
    25     int d=g[v].size();
    26     if(fa==-1)
    27         wide[v]=0;
    28     else
    29         wide[v]=wide[fa]+1;
    30     if(wide_max<wide[v])
    31         wide_max=wide[v];
    32     for(int i=0;i<d;i++){
    33         int k=g[v][i];
    34         if(k!=fa){
    35             dfs(k,f[k]=v);
    36         }
    37     }
    38 }
    39 void treeDP(int root){
    40     f[root]=-1;
    41     wide_max=-1;
    42     dfs(root,-1);
    43     for(int i=wide_max;i>=0;i--){
    44         for(int j=1;j<=n;j++){
    45             if(wide[j]==i){
    46                 dp[j]=son[j]+1;
    47                 if(i>=1)
    48                     son[f[j]]+=dp[j];
    49             }
    50         }
    51     }
    52 }
    53 int main()
    54 {
    55     cin>>T;
    56     while(T--){
    57         init();
    58         memset(son,0,sizeof(son));
    59         memset(dp,0,sizeof(dp));
    60         treeDP(1);
    61         int s=INF,pos;
    62         for(int i=1;i<=n;i++){
    63             int d=g[i].size();
    64             int ans=n-dp[i];
    65             for(int j=0;j<d;j++){
    66                 int k=g[i][j];
    67                 if(k!=f[i]){
    68                     ans=max(ans,dp[k]);
    69                 }
    70             }
    71             if(ans<s){
    72                 s=ans;
    73                 pos=i;
    74             }
    75         }
    76         printf("%d %d
    ",pos,s);
    77     }
    78     return 0;
    79 }
    View Code

     链接

    分析:求出数的所有重心,这个题时间卡得比较紧,不能用vector建图,要用链式前向星,关于链式前向星,这里有一篇很好的博客[点我]。同时要求我们在边求解的过程当中边标记。

     1 #include "iostream"
     2 #include "cstdio"
     3 #include "cstring"
     4 #include "string"
     5 using namespace std;
     6 const int maxn=50000+10;
     7 const int INF=1<<30;
     8 int n,cnt,s;
     9 int dp[maxn],f[maxn],vis[maxn];
    10 int head[maxn*2];
    11 struct Node
    12 {
    13     int to,next,w;
    14 };
    15 Node edge[maxn*2];
    16 void add(int x,int y){
    17     edge[cnt].to=y;
    18     edge[cnt].next=head[x];
    19     head[x]=cnt++;
    20 }
    21 void init(){
    22     scanf("%d",&n);
    23     memset(head,-1,sizeof(head));
    24     cnt=0;
    25     for(int i=1;i<n;i++){
    26         int x,y;
    27         scanf("%d%d",&x,&y);
    28         add(x,y);
    29         add(y,x);
    30     }
    31 }
    32 int dfs(int v,int fa){
    33     f[v]=fa;
    34     dp[v]=1;
    35     for(int i=head[v];i!=-1;i=edge[i].next){
    36         int k=edge[i].to;
    37         if(k!=f[v]){
    38             dp[v]+=dfs(k,v);
    39         }
    40     }
    41     int ans=n-dp[v];
    42     for(int i=head[v];i!=-1;i=edge[i].next){
    43         int k=edge[i].to;
    44         if(k==f[v])   continue;
    45         ans=max(ans,dp[k]);
    46     }
    47     vis[v]=ans;
    48     s=min(ans,s);
    49     return dp[v];
    50 }
    51 int main()
    52 {
    53     init();
    54     s=INF;
    55     dfs(1,-1);
    56     for(int i=1;i<=n;i++){
    57         if(vis[i]==s)
    58             printf("%d ",i);
    59     }
    60     printf("
    ");
    61 }
    View Code
  • 相关阅读:
    Eclipse
    svn 常用
    spidermonkey编译
    float format 显示
    点击6次修改服务器地址
    UITextField字数限制
    UINavigationController
    运行时runtime
    IOS 技术与面试
    Cocos2dx笔记
  • 原文地址:https://www.cnblogs.com/wolf940509/p/7373360.html
Copyright © 2011-2022 走看看