【一只蒟蒻的刷题历程】 【洛谷】 P1364-医院设置 (BFS || Floyed)

题目描述

设有一棵二叉树,如图:
在这里插入图片描述

其中,圈中的数字表示结点中居民的人口。圈边上数字表示结点编号,现在要求在某个结点上建立一个医院,使所有居民所走的路程之和为最小,同时约定,相邻接点之间的距离为 11。如上图中,若医院建在1 处,在这里插入图片描述

输入格式

第一行一个整数 n,表示树的结点数。

接下来的 n 行每行描述了一个结点的状况,包含三个整数 w, u, v,其中 w 为居民人口数,u 为左链接(为 0 表示无链接),v 为右链接(为 0 表示无链接)。

输出格式

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

输入输出样例

输入 #1

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

输出 #1

81

说明/提示

数据规模与约定

在这里插入图片描述


思路:

这题数据很小,只要可行的方法基本都可以过。

直接连接的两点的距离都看作1)

bfs: 每个点出发都走一遍bfs,更新最小点

floyed:先找出每两个点的最短距离,然后也是for一遍,更新最小点


代码一(BFS):

#include 
#include 
#include 
#include 
using namespace std;
const int maxn=110;

struct node{ //v是点的编号,step是距离
	int v,step;
	node(int a,int b){v=a;step=b;}
};

vector<int> g[maxn];  //邻接表
int n,u,v,w[maxn],ans=1<<27;  //w数组记录点权,ans初始值为很大的数

int bfs(int s) //bfs代码
{
	int sum=0;
	queue<node> q;
	bool inq[maxn]={false}; //记录是否入过队
	inq[s]=1;
	q.push(node(s,1)); //放入起点
    while(!q.empty())
	{
		int u=q.front().v;
		int step=q.front().step;
		q.pop(); 
		for(int i=0;i<g[u].size();i++)
		{
			int v=g[u][i];
			if(!inq[v])
			{
				inq[v]=1;
				q.push(node(v,step+1)); //下一层为当前step +1
				sum += w[v]*step; //累加值
			}
		}
	}
	return sum;
} 

int main() 
{
    cin>>n;
    for(int i=1;i<=n;i++)
    {
    	cin>>w[i]>>u>>v;
    	if(u) g[i].push_back(u),g[u].push_back(i); //无向图
    	if(v) g[i].push_back(v),g[v].push_back(i);
	}
	
	for(int i=1;i<=n;i++) //for一遍,找出最小值
	ans=min(ans,bfs(i));
		
    cout<<ans;
	return 0;
}

代码二(Floyed):

#include 
#include 
using namespace std;
const int maxn=110;
const int inf=1<<27;  //很大的数
int dis[maxn][maxn];  //记录两点距离
int n,u,v,w[maxn],ans=inf; //w为点权
int main() 
{
	fill(dis[0],dis[0]+maxn*maxn,inf); //初始化为很大的值
    cin>>n;
    for(int i=1;i<=n;i++)
    {
    	cin>>w[i]>>u>>v;
    	if(u) dis[i][u]=dis[u][i]=1; //直接相连的两点距离为1
    	if(v) dis[i][v]=dis[v][i]=1;
	}
	for(int k=1;k<=n;k++) //过一遍floyed
		for(int i=1;i<=n;i++)
			for(int j=1;j<=n;j++)
				if(dis[i][k]<inf && dis[k][j]<inf)
					dis[i][j]=min(dis[i][j],dis[i][k]+dis[k][j]);

	for(int i=1;i<=n;i++) //找出最小值
	{
		int sum=0;
		for(int j=1;j<=n;j++)
			if(i!=j) sum += w[j]*dis[i][j];
        ans =min(ans,sum);
	}	
	cout<<ans;
	return 0;
}

你可能感兴趣的:(#,搜索,#,最短路径)