题目地址:http://acm.hdu.edu.cn/showproblem.php?pid=3631
思路:Floyd,对于已求出最短路的图,若增加一点k及相应的边,则只需将k当做中间节点更新点u与点v的距离即可。因此,每增加一个标记点时,则将标记点当做中间节点更新最短路径,由于点数只有300,时间上可以承受。
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long LL;
const int maxn=300+50;
const int INF=0x3f3f3f3f;
int n,m,q;
int flag[maxn];
LL g[maxn][maxn];
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]);
}
}
}
void init()
{
for(int i=0; i<n; i++)
{
g[i][i]=0;
for(int j=0; j<n; j++)
if(i!=j) g[i][j]=INF;
}
memset(flag,0,sizeof(flag));
}
int main()
{
int cas=0;
while(scanf("%d%d%d",&n,&m,&q)!=EOF&&n)
{
cas++;
if(cas!=1) printf("\n");
printf("Case %d:\n",cas);
init();
for(int i=0; i<m; i++)
{
LL w;
int x,y;
scanf("%d%d%lld",&x,&y,&w);
g[x][y]=min(g[x][y],w);
}
for(int i=0; i<q; i++)
{
int cmd,x,y;
scanf("%d",&cmd);
if(cmd==0)
{
scanf("%d",&x);
if(flag[x]) printf("ERROR! At point %d\n",x);
else
{
Floyd(x);
flag[x]=1;
}
}
else
{
scanf("%d%d",&x,&y);
if(!flag[x]||!flag[y]) printf("ERROR! At path %d to %d\n",x,y);
else
{
if(g[x][y]>=INF) printf("No such path\n");
else printf("%lld\n",g[x][y]);
}
}
}
}
return 0;
}