floyed
简析
说明:f [ i ][ j ] 表示从 i 到 j 的距离。
floyed的思想就是先找到一个点 k ,然后依次遍历经过 k 的两个点 x,y 。
倘若原来记录 x 到 y 的距离大于 经过 x 经过 k 到 y的距离,就更新一下 x 到 y 的距离,即 f [ i ][ j ] = f [ i ][ k ] + f [ k ][ j ] 。
要注意的是它求的是最短路,所以要初始化 每个点到其他点的距离为 inf 。这里的 inf 是一个很大的值,保证更新的时候能找到最小值。
比方说,如果两点初始距离为 0,那如何也找不到更小的点更新了(除非是负数)。
而 f [ i ][ i ] 初始化为 0 ,因为自己到自己的距离显然是 0。(这里运用了显然论证法。
但如果要求的是最长路,那就不用初始化了。
特别注意
这里输出 impossible 的条件为 if ( f [ x ][ y ] > inf / 2 )。
因为题中说有负数的点,所以更新时也许会让不连通的点略小一点。
例如f [ i ][ k ]为负数,f [ k ][ j ] 不连通( inf ),f [ i ][ j ] 不连通( inf ),那就会更新 f [ i ][ j ] 使其略小于 inf 。
那题目中如果说没有负数,那条件就是 if( f [ x ][ y ] == inf)。
上代码
#include<iostream>
using namespace std;
inline int read(){//快读
    int x=0,f=1;
    char ch=getchar();
    while(ch<'0'||ch>'9'){
        if(ch=='-')
            f=-1;
        ch=getchar();
    }
    while(ch>='0' && ch<='9')
        x=x*10+ch-'0',ch=getchar();
    return x*f;
}
#define N 20010
#define inf 0x3f3f3f3f
int n,m,p,f[N][N];
int main(){
    n=read();m=read();p=read();
    for(int i=1;i<=n;i++){//初始化
        for(int j=1;j<=n;j++){
            if(i==j)
                f[i][j]=0;
            else
                f[i][j]=inf;
        }
    }
    for(int i=1;i<=m;i++){//读入
        int u,v,w;
        u=read();v=read();w=read();
        f[u][v]=min(f[u][v],w);//考虑题目可能会恶心你
    }
    for(int k=1;k<=n;k++){//找点
        for(int i=1;i<=n;i++){
            for(int j=1;j<=n;j++){
                if(f[i][j]>f[i][k]+f[k][j])
                    f[i][j]=f[i][k]+f[k][j];
            }
        }
    }
    for(int i=1;i<=p;i++){//判断,输出
        int x,y;
        x=read();
        y=read();
        if(f[x][y]>inf/2)
            cout<<"impossible"<<endl;
        else
            cout<<f[x][y]<<endl;
    }
    return 0;
}本文来自博客园,作者:huaziqi 转载请注明原文链接:https://www.cnblogs.com/huaziqi/p/16245446.html

 
                
            
         浙公网安备 33010602011771号
浙公网安备 33010602011771号