思路:最短路+floyd
分析:
1 题目给的n <= 300,而边数m<=100000,并且有Q<= 100000次询问。刚开始我用优先队列+Dij然后就开始TLE,然后就没然后了。
2 看了题解之后猛然发现这尼玛就是floyd,(对算法理解不透测)。我们知道floyd就是每次都拿一个中间点k来更新dis,题目中是只有标记过的点才能够使用,那么就像floyd一样只要是标记来这个点那么就可以用这个点来进行更新dis,然后如果要求两点直间的距离只要查找即可。
代码:
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
using namespace std;
#define MAXN 310
#define INF 0xFFFFFFF
int n , m , Q , cnt , flag;
int vis[MAXN];
int weight[MAXN][MAXN];
void init(){
for(int i = 0 ; i < n ; i++){
vis[i] = 0;
for(int j = 0 ; j < n ; j++)
weight[i][j] = INF;
weight[i][i] = 0;
}
}
int min(int a , int b){
return a < b ? a : b;
}
void floyd(int s){
for(int i = 0 ; i < n ; i++){
for(int j = 0 ; j < n ; j++)
weight[i][j] = min(weight[i][s]+weight[s][j] , weight[i][j]);
}
}
int main(){
int x , s , e , v;
cnt = 1;
flag = 1;
while(scanf("%d%d%d" , &n , &m , &Q) && n+m+Q){
init();
for(int i = 0 ; i < m ; i++){
scanf("%d%d%d" , &s , &e , &v);
if(weight[s][e] > v)
weight[s][e] = v;
}
if(!flag)
printf("\n");
else
flag = 0;
printf("Case %d:\n" , cnt++);
for(int i = 0 ; i < Q ; i++){
scanf("%d" , &x);
if(!x){
scanf("%d" , &s);
if(!vis[s]){
vis[s] = 1;
floyd(s);/*更新dis*/
}
else
printf("ERROR! At point %d\n" , s);
}
else{
scanf("%d%d" , &s , &e);
if(!vis[s] || !vis[e])
printf("ERROR! At path %d to %d\n" , s , e);
else{
if(weight[s][e] == INF)
printf("No such path\n");
else
printf("%d\n" , weight[s][e]);
}
}
}
}
return 0;
}