Floyd模板题 P1704

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;
}
原文地址:https://www.cnblogs.com/virtual-north-Illya/p/10045089.html