HDU 2680 Choose the best route 最短路

题意: 第一行三个数n m t 代表 n个点 m条边 终点是t 接下来m行每行三个数 u v d 代表从u 到 v 距离为 d 再一行 一个数x 代表有x个起点 接下来一行有x个数 代表这x个起点 让你求从这些起点到终点的最短路 没有的话输出-1

思路:其实这道题看似多个起点 要求多次最短路 但是如果加一个虚节点 将多个起点连起来 这不就是经典的单源最短路了吗 - -

这题我用的是SPFA 但是速度居然没有Dijkstra快!! 的确SPFA很不稳定啊...

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;

#define REP(i, a, b) for( int i = a; i < b; i++ )
#define CLR(a, x) memset( a, x, sizeof a )

const int maxn = 1000 + 10;
const int maxe  = 20000 + 10;
const int INF = 1e9;

struct Edge{
          int v, d;
          int next;
          Edge(){}
          Edge(int v, int d, int next) : v(v), d(d), next(next){}
};

struct SPFA{
          int top, cntE, n;
          int Head[maxn], vis[maxn], cnt[maxn], STACK[maxn], dist[maxn];
          Edge edge[maxe];
          void init(int n){
                    this -> n = n;
                    CLR(Head, -1);
                    CLR(vis, 0);
                    cntE = top = 0;
          }
          void add(int u, int v, int d){
                    edge[cntE] = Edge(v, d, Head[u]);
                    Head[u] = cntE++;
          }
          bool spfa(int s){
                    CLR(vis, 0);
                    CLR(cnt, 0);
                    vis[s] = cnt[s] = 1;
                    STACK[top++] = s;
                    REP(i, 0, n) dist[i] = INF;
                    dist[s] = 0;
                    while(top){
                              int u = STACK[--top];
                              vis[u] = 0;
                              for(int i = Head[u]; ~i; i = edge[i].next){
                                        int v = edge[i].v;
                                        if(dist[v] > dist[u] + edge[i].d){
                                                  dist[v] = dist[u] + edge[i].d;
                                                  if(!vis[v]){
                                                            vis[v] = 1;
                                                            STACK[top++] = v;
                                                            if(++cnt[v] > n) return false;
                                                  }
                                        }
                              }
                    }
                    return true;
          }
}Spfa;

int n, m, T, u, v, d;

void solve(){
          Spfa.init(n + 1);
          REP(i, 0, m){
                    scanf("%d%d%d", &u, &v, &d);
                    Spfa.add(u, v, d);
          }
          scanf("%d", &u);
          while(u--){
                    scanf("%d", &v);
                    Spfa.add(0, v, 0);
          }
          if(Spfa.spfa(0)){
                    if(Spfa.dist[T] < INF) printf("%d\n", Spfa.dist[T]);
                    else puts("-1");
          }
          else puts("-1");
}

int main()
{
//          freopen("in.txt", "r", stdin);
          while(~scanf("%d%d%d", &n, &m, &T)) solve();
          return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值