hdu 3631 Shortest Path

点击打开链接hdu 3631


思路:最短路+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;
}


你可能感兴趣的:(算法,Path)