【模板】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;
}