C++ 最短路(Floyd) 洛谷

【模板】Floyd

题目描述

给出一张由 n 个点 m 条边组成的无向图。

求出所有点对 (i,j) 之间的最短路径。

输入格式

第一行为两个整数 n,m,分别代表点的个数和边的条数。

接下来 m 行,每行三个整数 u,v,w,代表 u,v之间存在一条边权为 w 的边。

输出格式

输出 n 行每行 n 个整数。

第 i 行的第 j 个整数代表从 i 到 j 的最短路径。

#include<bits/stdc++.h>
#define int long long
 
using namespace std;
 
const int N = 200;
 
int n,m;
int dis[N][N];

void floyd()
{
	for(int k = 1;k<=n;k++)
	{
		for(int i = 1;i<=n;i++)
		{
			for(int j = 1;j<=n;j++)
			{
				dis[i][j] = min(dis[i][j],dis[i][k]+dis[k][j]);
			}
		}
	}
}

signed main()
{
	cin>>n>>m;
	for(int i = 1;i<=n;i++)
	{
		for(int j = 1;j<=n;j++)
		{
			dis[i][j] = 1e18;
			if(i==j) dis[i][j] = 0;
		}
	}
	while(m--)
	{
		int a,b,c;
		cin>>a>>b>>c;
		dis[a][b] = min(dis[a][b],c);
		dis[b][a] = min(dis[a][b],c);
	}
	floyd();
	for(int i = 1;i<=n;i++)
	{
		for(int j = 1;j<=n;j++)
		{
			cout<<dis[i][j]<<" ";
		}
		cout<<"\n";
	}
	
	return 0; 
}

[USACO07NOV] Cow Hurdles S

题目描述

Farmer John 想让她的奶牛准备郡级跳跃比赛,Bessie 和她的伙伴们正在练习跨栏。她们很累,所以她们想消耗最少的能量来跨栏。 显然,对于一头奶牛跳过几个矮栏是很容易的,但是高栏却很难。于是,奶牛们总是关心路径上最高的栏的高度。

奶牛的训练场中有 N 个站台,分别标记为 1,…,N。所有站台之间有 M 条单向路径,第 i 条路经是从站台 Si​ 开始,到站台 Ei​,其中最高的栏的高度为 Hi​。无论如何跑,奶牛们都要跨栏。

奶牛们有 T 个训练任务要完成。第 ii 个任务包含两个数字 Ai​ 和 Bi​,表示奶牛必须从站台 Ai​ 跑到站台 Bi​,可以路过别的站台。奶牛们想找一条路径从站台 Ai​ 到站台 Bi​,使路径上最高的栏的高度最小。 你的任务就是写一个程序,计算出路径上最高的栏的高度的最小值。

输入格式

第一行:三个空格隔开的整数 N,M,T。

接下来 M 行:第 i 行包含三个空格隔开的整数 Si,Ei,Hi​。

接下来 T 行:第 i 行包含两个空格隔开的整数,表示任务 i 的起始站台和目标站台 Ai,Bi​。

输出格式

T 行:第 i 行为一个整数,表示任务 i 路径上最高的栏的高度的最小值。如果无法到达,输出 -1

方法一:
#include<bits/stdc++.h>
using namespace std;
int n,m,t,dis[1000][1000],a,b,c,x,y;
int main()
{
	cin>>n>>m>>t;
	memset(dis,0x7f,sizeof(dis));
	for(int i=1;i<=m;i++)
	{
		cin>>a>>b>>c;
		dis[a][b]=c;
	}
	for(int k=1;k<=n;k++)
	{
		for(int i=1;i<=n;i++)
		{
			for(int j=1;j<=n;j++)
			{
				int s=max(dis[i][k],dis[k][j]);
				if(s!=0x7f7f7f7f&&s<dis[i][j])
				{	 
					dis[i][j]=s;
				}
			}
		}
	}
	for(int i=1;i<=t;i++){
		cin>>x>>y;
		if(dis[x][y]==0x7f7f7f7f)
		{
			cout<<-1<<endl;
			continue;
		}
		cout<<dis[x][y]<<endl;
	}
	return 0;
}
方法二:
#include<bits/stdc++.h>

#define IOS std::ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
#define int long long

using namespace std;

const int N = 310;

int n,m,T;
int dis[N][N];

signed main()
{
	IOS;
	cin>>n>>m>>T;
	for(int i=1;i<=n;i++)
	{
		for(int j=1;j<=n;j++)
		{
			dis[i][j] = 1e18;
			if(i==j) dis[i][j] = 0;
		}
	}
	while(m--)
	{
		int a,b,c;
		cin>>a>>b>>c;
		dis[a][b] = c;
	}
	for(int k=1;k<=n;k++)
	{
		for(int i=1;i<=n;i++)
		{
			for(int j=1;j<=n;j++)
			dis[i][j] = min(dis[i][j],max(dis[i][k],dis[k][j]));
		}
	}
	while(T--)
	{
		int a,b;
		cin>>a>>b;
		if(dis[a][b]==1e18) cout<<-1<<"\n";
		else cout<<dis[a][b]<<"\n";
	}
	return 0;
}

采购特价商品

题目背景

《爱与愁的故事第三弹·shopping》第一章。

题目描述

中山路店山店海,成了购物狂爱与愁大神的“不归之路”。中山路上有 n(n≤100)家店,每家店的坐标均在 −10000至 10000之间。其中的 m 家店之间有通路。若有通路,则表示可以从一家店走到另一家店,通路的距离为两点间的直线距离。现在爱与愁大神要找出从一家店到另一家店之间的最短距离。你能帮爱与愁大神算出吗?

输入格式

共 n+m+3 行:

第一行:整数 n。

接下来 n 行:每行两个整数 x 和 y,描述了一家店的坐标。

接下来一行:整数 m。

接下来 m 行:每行描述一条通路,由两个整数 i 和 j 组成,表示第 i 家店和第 j 家店之间有通路。

接下来一行:两个整数 s 和 t,分别表示原点和目标店。

输出格式

仅一行:一个实数(保留两位小数),表示从 s 到 t 的最短路径长度。

#include<bits/stdc++.h>
#define int long long
 
using namespace std;
 
const int N = 200;
int n,m;
double dis[N][N];
pair<int,int> va[N];

void floyd()
{
	for(int k = 1;k<=n;k++)
	{
		for(int i = 1;i<=n;i++)
		{
			for(int j = 1;j<=n;j++)
			{
				dis[i][j] = min(dis[i][j],dis[i][k]+dis[k][j]);
			}
		}
	}
}

signed main()
{
	cin>>n;
	for(int i = 1;i<=n;i++)
	{
		cin>>va[i].first>>va[i].second;
	}
	for(int i = 1;i<=n;i++)
	{
		for(int j = 1;j<=n;j++)
		{
			dis[i][j] = 1e18;
			if(i==j) dis[i][j] = 0;
		}
	}
	cin>>m;
	while(m--)
	{
		int a,b;
		cin>>a>>b;
		double sum = 0;
		sum += (va[a].first-va[b].first)*(va[a].first-va[b].first);
		sum += (va[a].second-va[b].second)*(va[a].second-va[b].second);
		sum = sqrt(sum);
		dis[a][b] = min(dis[a][b],sum);
		dis[b][a] = min(dis[b][a],sum);
	}
	floyd();
	int s,t;
	cin>>s>>t;
	
	
	printf("%.2lf",dis[s][t]);
	return 0; 
}

医院设置

题目描述

设有一棵二叉树,如图:

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

输入格式

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

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

输出格式

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

#include<bits/stdc++.h>
#define fi first
#define se second
#define pb push_back
#define PII pair<int,int >
#define int long long 
#define IOS std::ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);

using namespace std;

const int N = 305;
int dis[N][N];
int n;
int va[N];

void floyd()
{
	for(int k = 1;k<=n;k++)
	{
		for(int i = 1;i<=n;i++)
		{
			for(int j = 1;j<=n;j++)
			{
				dis[i][j] = min(dis[i][j],dis[i][k]+dis[k][j]);
			}
		}
	}
}

signed main()
{
	cin>>n;
	int c,a,b;
	for(int i = 1;i<=n;i++)
	{
		for(int j = 1;j<=n;j++)
		{
			dis[i][j] = 1e18;
			if(i==j) dis[i][j] = 0;
		}
	}
	for(int i = 1;i<=n;i++)
	{
		
		cin>>va[i]>>a>>b;
		if(a!=0) dis[i][a] = dis[a][i] = 1;
		if(b!=0) dis[i][b] = dis[b][i] = 1;
	}
	floyd();
	int minn = 1e18;
	for(int k = 1;k<=n;k++)
	{
		int sum = 0;
		for(int i = 1;i<=n;i++)
		{
			sum+=dis[i][k]*va[i];	
		}
		minn = min(minn,sum);
	}
	cout<<minn;
	return 0;
}

  • 17
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值