首页 > 代码库 > 51Nod 1737 配对(树的重心)

51Nod 1737 配对(树的重心)

http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1737

题意:

技术分享

 

思路:

树的重心。

树的重心就是其所以子树的最大的子树结点数最少,删除这个点后最大连通块的结点数最小,也就说各个连通块尽量平衡。

这道题的话就是先求一个重心,然后求各个点到重心的距离之和。

 1 #include<iostream> 2 #include<algorithm> 3 #include<cstring> 4 #include<cstdio> 5 #include<vector> 6 #include<queue> 7 #include<cmath> 8 #include<map> 9 using namespace std;10 11 const int maxn=1e5+5;12 const int INF=0x3f3f3f3f;13 14 int n;15 16 vector<pair<int,int> > edge[maxn];17 18 int zx,sz;19 int son[maxn],vis[maxn];20 long long ww[maxn];   //各个点到重心的距离21 22 void init()23 {24     for(int i=1;i<=n;i++)25         edge[i].clear();26     memset(vis,0,sizeof(vis));27     memset(ww,0,sizeof(ww));28     sz=INF;29     zx=-1;30 }31 32 void dfs(int u)33 {34     vis[u]=1;35     son[u]=0;36     int temp=0;37     for(int i=0;i<edge[u].size();i++)38     {39         int v=edge[u][i].first;40         if(!vis[v])41         {42             dfs(v);43             son[u]+=son[v]+1;    //找到该子树中的最大结点数44             temp=max(temp,son[v]+1);45         }46     }47     temp=max(temp,n-son[u]-1);    //删去重心后子树最大结点数和非重心的子树比较48     if(temp<sz)49     {50         zx=u;51         sz=temp;52     }53 }54 55 void sum(int u)56 {57     vis[u]=1;58     for(int i=0;i<edge[u].size();i++)59     {60         int v=edge[u][i].first;61         if(!vis[v])62         {63             ww[v] =ww[u]+edge[u][i].second;64             sum(v);65         }66     }67 }68 69 int main()70 {71     //freopen("D:\\input.txt","r",stdin);72     while(~scanf("%d",&n))73     {74         init();75         int u,v,w;76         for(int i=1;i<=n-1;i++)77         {78             scanf("%d%d%d",&u,&v,&w);79             edge[u].push_back(make_pair(v,w));80             edge[v].push_back(make_pair(u,w));81         }82 83         dfs(1);84         memset(vis,0,sizeof(vis));85         sum(zx);86         long long ans=0;87         for(int i=1;i<=n;i++)88             ans+=ww[i];89         printf("%lld\n",ans);90     }91 }

 

51Nod 1737 配对(树的重心)