Shortest Path
题意:
给n、m、q,表示n个点m条边q个询问
每个询问两种方式
0 x,表示标记x,如果已经被标记就输出ERROR! At point x
1 x y,表示输出x到y的最短距离,要求x和y都及其最短路径上的点都被标记过,如果x或y没有被标记输出ERROR! At path x to y,如果x到y之间没有路径就输出No such path
Sample Input
5 10 10
1 2 6335
0 4 5725
3 3 6963
4 0 8146
1 2 9962
1 0 1943
2 1 2392
4 2 154
2 2 7422
1 3 9896
0 1
0 3
0 2
0 4
0 4
0 1
1 3 3
1 1 1
0 3
0 4
0 0 0
Sample Output
Case 1:
ERROR! At point 4
ERROR! At point 1
0
0
ERROR! At point 3
ERROR! At point 4
分析:
插点法,又是没听过的名字,记下来
每当我们标记一个点,就以标记的这个点作为floyd过程中的中间节点k,用这个k更新所有点间的最短路
code:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
const int inf=0x3f3f3f3f;
const int inn=0x80808080;
using namespace std;
const int maxm=305;
int g[maxm][maxm];
int mark[maxm];
int n,m,q;
void init(){
memset(g,inf,sizeof g);
for(int i=0;i<n;i++)g[i][i]=0;
memset(mark,0,sizeof mark);
}
void floyd(int k){
for(int i=0;i<n;i++){
for(int j=0;j<n;j++){
g[i][j]=min(g[i][j],g[i][k]+g[k][j]);
}
}
}
int main(){
int cas=1;
while(scanf("%d%d%d",&n,&m,&q)!=EOF){
if(!n&&!m&&!q)break;
if(cas-1)puts("");
init();
for(int i=1;i<=m;i++){
int a,b,c;
scanf("%d%d%d",&a,&b,&c);
g[a][b]=min(g[a][b],c);
}
printf("Case %d:\n",cas++);
while(q--){
int d;
scanf("%d",&d);
if(d==0){
int x;
scanf("%d",&x);
if(!mark[x]){
mark[x]=1;
floyd(x);
}else{
printf("ERROR! At point %d\n",x);
}
}else{
int a,b;
scanf("%d%d",&a,&b);
if(!mark[a]||!mark[b]){
printf("ERROR! At path %d to %d\n",a,b);
}else{
if(g[a][b]==inf){
printf("No such path\n");
}else{
printf("%d\n",g[a][b]);
}
}
}
}
}
return 0;
}