今天打算开始写模板了(
那就发在博客里好了。
简析说明: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)。
上代码#includeusing 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"<



