【图论】【最短路】医院设置

Description

设有一棵二叉树(如右图)。其中,圈中的数字表示结点中居民的人口。圈边上数字表示结点编号,现在要求在某个结点上建立一个医院,使所有居民所走的路程之和为最小,同时约定,相邻接点之间的距离为1。如 右图中,若医院建在:
  1处,则距离和=4+12+220+240=136
  3处,则距离和=4*2+13+20+40=81
    ………….

Input

第一行一个整数n,表示树的结点数。(n<=100)
接下来的n行每行描述了一个结点的状况,包含三个整数,整数之间用空格(一个或多个)分隔,其中:第一个数为居民人口数;第二个数为左链接,为0表示无链接;第三个数为右链接。

Output

一个整数,表示最小距离和。

Sample Input

5
13 2 3
4 0 0
12 4 5
20 0 0
40 0 0

Sample Output

81


解题思路

先枚举起点,求出最短路后用 最短路 x 人数,比较出最小的
SPFA的处理会麻烦:

  • 输入边的时候,因为是无向图,所以一共要存4条边
  • 如果是0,必须排除,不然会连到0,就中断了。

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
struct DT{
	int to,next;
}a[30000];
int dis[10000],head[10000],n,num,lt[10000];
int h,t,v[10000],f[10000];
long long Gun=0x7fffffff;
void SPFA(int s){
	memset(f,0,sizeof(f));
	h=0,t=1,v[1]=s,dis[s]=0,f[s]=1;
	while(h++<t){
		for(int i=head[v[h]];i;i=a[i].next){
			if(dis[v[h]]+1<dis[a[i].to]){
				dis[a[i].to]=dis[v[h]]+1;
				if(!f[a[i].to]){
					v[++t]=a[i].to;
					f[a[i].to]=1;
				}
			}
		}
		f[v[h]]=0;
	}
}
int main(){
	scanf("%d",&n);
	for(int i=1;i<=n;i++){
		int x,y,s;
		scanf("%d%d%d",&lt[i],&x,&y);
		if(y>0){//右链接
			a[++num].to=y,a[num].next=head[i],head[i]=num;
    		a[++num].to=i,a[num].next=head[y],head[y]=num;
		}
		if(x>0){//左连接
	    	a[++num].to=x,a[num].next=head[i],head[i]=num;
	    	a[++num].to=i,a[num].next=head[x],head[x]=num;
		}
	} 
	for(int g=1;g<=n;g++){//枚举起点
		memset(dis,0x7f,sizeof(dis));
		SPFA(g);
		long long b=0;
		for(int i=1;i<=n;i++)
		    b+=lt[i]*dis[i]; //人数 x 最短路
		Gun=min(Gun,b);
	}
	printf("%lld",Gun);
}

发布了45 篇原创文章 · 获赞 0 · 访问量 344

猜你喜欢

转载自blog.csdn.net/qq_39940018/article/details/103995492