题意
有n个点,m条有向边,q个询问,询问有两种操作,0和1,0操作输入一个x,将点x标记,如果x点在之前的操作已经被标记过了就输出 ERROR! At point x,否则标记这个点。1操作要求输入两个点x和y,如果x点没有被标记或者y点没有被标记,输出 ERROR! At path x to y ,否则输出x,y两点间的最短距离(求最短距离的时候只能根据已经被标记的点求),如果两点无法到达,输出No such path,否则输出最短距离。格式要注意,两个测试例子之间要输出一个空格。
思路
根据floyd求最短路,每次标记一个点x的时候,就根据x更新一次最短距离。
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
const int MAX_N = 310;
const int MAX_M = 100010;
const int inf = 0x3f3f3f3f;
int Map[MAX_N][MAX_N];
int n, m, q;
int vis[MAX_N];
void floyd(int x) {
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= n; j++) {
Map[i][j] = min(Map[i][j], Map[i][x] + Map[x][j]);
}
}
}
int main() {
int k = 0;
while (scanf("%d%d%d", &n, &m, &q) != EOF) {
if (n == 0 && m == 0 && q == 0)break;
k++;
memset(vis, -1, sizeof vis);
memset(Map, inf, sizeof Map);
for (int i = 1; i <= n; i++)Map[i][i] = 0;
for (int i = 1; i <= m; i++) {
int x, y, z;
scanf("%d%d%d", &x, &y, &z);
x++, y++;
Map[x][y] = min(Map[x][y], z);
}
if (k != 1)
printf("\n");
printf("Case %d:\n", k);
for (int i = 1; i <= q; i++) {
int opt, x, y;
scanf("%d", &opt);
if (opt == 0) {
scanf("%d", &x);
x++;
if (vis[x] == 0) {
printf("ERROR! At point %d\n", --x);
}
else {
vis[x] = 0;
floyd(x);
}
}
else if (opt == 1) {
scanf("%d%d", &x, &y);
x++, y++;
if (vis[x] == -1 || vis[y] == -1) {
printf("ERROR! At path %d to %d\n", --x, --y);
}
else if (Map[x][y] == inf) {
printf("No such path\n");
}
else {
printf("%d\n", Map[x][y]);
}
}
}
}
return 0;
}