n个点从0 , 1, 2 ,3.....n-1,这些点只有被标记过之后才能走,求给出的两点之间的最短路。
Floyd的思想拿来插点。很容易想到两种更新两点之间距离的大概思路:
1:给出的两点X,Y,遍历所有点看是否能够松弛,即dis【X】【Y】 = MIN(dis【x】【i】 + dis【i】【Y】)。
2:对每次给出的新的标记的点Z,以其为松弛点遍历整张图里的点对之间距离,即dis【i】【j】 = MIN(dis【i】【Z】, dis【Z】【j】)。
但实际上第一种更新是错的,因为只松弛了i的点而其他点对之间还没有松弛。第二种的时间是O(N^2*K)
#include<stdio.h>
#include<string.h>
#include<string.h>
#include<algorithm>
#include<queue>
using namespace std;
const int N = 305;
const int inf = 1 << 28;
int a[N][N];
int used[N], vis[N], dis[N];
int n, m, k;
void init()
{
for( int i = 0; i <= n; i++ )
{
used[i] = vis[i] = 0;
dis[i] = inf;
for( int j = 0; j <= n; j++ )
{
a[i][j] = (i == j? 0: inf);
}
}
}
void floyd(int mid)
{
for( int i = 0; i < n; i++ )
{
for( int j = 0; j < n; j++ )
{
a[i][j] = min(a[i][j], a[i][mid] + a[mid][j]);
}
}
}
int main()
{
int cas = 1;
while(~scanf("%d%d%d", &n, &m, &k) && (n || m || k))
{
init();
int u, v, w;
while(m--)
{
scanf("%d%d%d", &u, &v, &w);
a[u][v] = min(a[u][v], w);
}
int x, y, z;
//floyd();
if( cas > 1 )
puts("");
printf("Case %d:\n", cas++);
while(k--)
{
int op;
scanf("%d", &op);
if( op == 1 )
{
scanf("%d%d", &x, &y);
if( !used[x] || !used[y] )
{
printf("ERROR! At path %d to %d\n", x, y);
continue;
}
if( a[x][y] < inf )
printf("%d\n", a[x][y]);
else
puts("No such path");
}
else
{
scanf("%d", &z);
if( used[z] )
printf("ERROR! At point %d\n", z);
else
{
used[z] = 1;
floyd(z);
}
}
}
}
return 0;
}