本题对floyd算法进行变形。floyd的核心代码是
for(int k = 0; k < n; k++)
for(int i = 0; i < n; i++)
for(int j = 0; j < n; i++) {
dist[i][j] = min(dist[i][j], dist[i][j] + dist[k][j])
}
此题将i到j要用到的中间转移点k分散给出,我们只要想到这点就可以完成此题。当给出一个k时,我们用
for(int i = 0; i < n; i++)
for(int j = 0; j < n; j++) {
if(dist[i][k]!= inf && dist[k][i] != inf && dist[i][j] > dist[i][k] + dist[k][j]) //dist[i][k] != inf 表示 i 和 k 间联通,同理 dist[k][i] != inf;
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
const int M = 305;
const int inf = 0x7fffffff;
int dist[M][M];
int mark[M];
int n, m, q, cnt= 1;
void init() {
for(int i = 0; i < n; i++){
mark[i] = 0;
for(int j = 0; j < n; j++){
if(i == j)
dist[i][j] = 0;
else
dist[i][j] = inf;
}
}
if(cnt != 1)
printf("\n");
}
void input() {
int a, b, d;
for(int i = 0; i < m; i++) {
scanf("%d%d%d", &a, &b, &d);
dist[a][b] = min(dist[a][b], d);
}
}
void floyd(int& k) {
for(int i = 0; i < n; i++){
for(int j = 0; j < n; j++) {
if(dist[i][k] != inf && dist[k][j] != inf && dist[i][j] > dist[i][k] + dist[k][j]){
dist[i][j] = dist[i][k] + dist[k][j];
}
}
}
}
void work() {
int flag, x, y;
printf("Case %d:\n", cnt++);
for(int i = 0; i < q; i++) {
scanf("%d", &flag);
if(!flag){
scanf("%d", &x);
if(mark[x]){
printf("ERROR! At point %d\n", x);
}else {
floyd(x);
mark[x] = 1;
}
}else {
scanf("%d%d",&x, &y);
if(!mark[x] || !mark[y])
printf("ERROR! At path %d to %d\n", x, y);
else {
if(dist[x][y] == inf)
printf("No such path\n");
else
printf("%d\n", dist[x][y]);
}
}
}
}
int main()
{
while(scanf("%d%d%d", &n, &m, &q) != EOF &&(n || m || q)) {
init();
input();
work();
}
return 0;
}
dist[i][j] = dist[i][k] + dist[k][j];
}