题意:给出一棵树,每个节点有权值,让我们确定在哪个地方安装医院,距离最短?
何为距离?你猜
思路:这道题给出的n的范围只有100,所以很明显我们可以直接暴力n^2搜答案,这可以过
代码如下
1 #include<bits/stdc++.h> 2 using namespace std; 3 const int maxn=1e2+10; 4 const int inf=0x3f3f3f3f; 5 int a[maxn]; 6 struct node 7 { 8 int v,nxt; 9 }G[maxn<<1]; 10 int head[maxn];int num; 11 void add(int u,int v) 12 { 13 G[++num].v=v;G[num].nxt=head[u];head[u]=num; 14 } 15 int ans=inf; 16 int sum=0; 17 void dfs(int u,int fa,int step) 18 { 19 sum+=a[u]*step; 20 for(int i=head[u];i;i=G[i].nxt){ 21 int v=G[i].v; 22 if(v==fa) continue; 23 dfs(v,u,step+1); 24 } 25 } 26 int main() 27 { 28 int n; 29 scanf("%d",&n); 30 for(int i=1;i<=n;i++){ 31 int w,u,v; 32 scanf("%d%d%d",&w,&u,&v); 33 a[i]=w; 34 if(u) add(i,u),add(u,i); 35 if(v) add(i,v),add(v,i); 36 } 37 for(int i=1;i<=n;i++){ 38 sum=0; 39 dfs(i,0,0); 40 ans=min(ans,sum); 41 } 42 printf("%d\n",ans); 43 return 0; 44 }
但是:假如n的范围是1e5呢,就过不去了
所以我们可以用树的重心来解决这道题
树的重心有以下性质:
1、树上所有的点到树的重心的距离之和是最短的,如果有多个重心,那么总距离相等。
2、插入或删除一个点,树的重心的位置最多移动一个单位。
3、若添加一条边连接2棵树,那么新树的重心一定在原来两棵树的重心的路径上。
我们只需要用到第一条性质,将题目中给出的节点权值转化为节点个数就跟树的重心一模一样了
然后,求出哪个位置为重心后,我们就再枚举一遍即可
1 #include<bits/stdc++.h> 2 using namespace std; 3 const int maxn=1e2+10; 4 const int inf=0x3f3f3f3f; 5 int a[maxn]; 6 struct node 7 { 8 int v,nxt; 9 }G[maxn<<1]; 10 int head[maxn];int num; 11 void add(int u,int v) 12 { 13 G[++num].v=v;G[num].nxt=head[u];head[u]=num; 14 } 15 int ans=inf; 16 int sum; 17 int mxnode=0; 18 int mxnum=inf; 19 int siz[maxn]; 20 void dfs(int u,int fa,int step) 21 { 22 siz[u]=a[u]; 23 int tmp=0; 24 for(int i=head[u];i;i=G[i].nxt){ 25 int v=G[i].v; 26 if(v==fa) continue; 27 dfs(v,u,step+1); 28 siz[u]+=siz[v]; 29 tmp=max(tmp,siz[v]); 30 } 31 tmp=max(tmp,sum-siz[u]); 32 if(mxnum>tmp){ 33 mxnum=tmp; 34 mxnode=u; 35 } 36 } 37 void dfs1(int u,int fa,int step) 38 { 39 sum+=a[u]*step; 40 for(int i=head[u];i;i=G[i].nxt){ 41 int v=G[i].v; 42 if(v==fa) continue; 43 dfs1(v,u,step+1); 44 } 45 } 46 int main() 47 { 48 int n; 49 scanf("%d",&n); 50 for(int i=1;i<=n;i++){ 51 int w,u,v; 52 scanf("%d%d%d",&w,&u,&v); 53 a[i]=w; 54 sum+=w; 55 if(u) add(i,u),add(u,i); 56 if(v) add(i,v),add(v,i); 57 } 58 dfs(1,0,0); 59 //printf("%d\n",mxnode); 60 sum=0; 61 dfs1(mxnode,0,0); 62 printf("%d\n",sum); 63 return 0; 64 }