Description
给出N个顶点,M条无向带权边的连通图,和Q个查询:请编程回答:
问1、两点之间的最短路径(边权和最小的路径);
问2、两点之间的所有路径中,需要经过的最小边的最大的路径(最大边最小);
问3、两点之间的所有路径中,需要经过的的最大边的最小的路径(最小边最大);
Input
第一行:N(N<=400),M(M<=10000),Q(Q<=100)查询数量。接下来M行,每行三个整数:x,y,t(1<=x,y<=N)
Output
包含Q行,对应输入数据中的查询。
Hint
N<=400M<=10000
Solution
Floyd模板题。可以处理负权图,时间复杂度是O(n^3)。比较慢但是简单啊。
#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#define maxn 405
#define inf 0x3f3f3f3f
using namespace std;
int dist1[maxn][maxn],dist2[maxn][maxn],dist3[maxn][maxn],g[maxn][maxn];
int n,m,q,s,t,x,y,z;
void init(){
scanf("%d%d%d",&n,&m,&q);
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
if(i==j)g[i][j]=0;
else g[i][j]=inf;
}
}
for(int i=1;i<=m;i++){
int x,y,z;
scanf("%d%d%d",&x,&y,&z);
g[x][y]=z;
g[y][x]=z;
}
}
void floyd(){
memcpy(dist1,g,sizeof(dist1));
for(int k=1;k<=n;k++){
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
if(dist1[i][k]+dist1[k][j]<=dist1[i][j]){
dist1[i][j]=dist1[i][k]+dist1[k][j];
}
}
}
}
}
void floyd_max(){
memcpy(dist2,g,sizeof(dist2));
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
if(dist2[i][j]==inf)dist2[i][j]=-inf;
}
}
for(int k=1;k<=n;k++){
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
int tmp=min(dist2[i][k],dist2[k][j]);
dist2[i][j]=max(dist2[i][j],tmp);
}
}
}
}
void floyd_min(){
memcpy(dist3,g,sizeof(dist3));
for(int k=1;k<=n;k++){
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
int tmp=max(dist3[i][k],dist3[k][j]);
dist3[i][j]=min(dist3[i][j],tmp);
}
}
}
}
int main(){
init();
floyd();
floyd_max();
floyd_min();
for(int i=1;i<=q;i++){
scanf("%d%d",&s,&t);
printf("%d %d %d
",dist1[s][t],dist2[s][t],dist3[s][t]);
}
return 0;
}