HDU 2066 一个人的旅行(单源最短路SPFA)

Description

虽然草儿是个路痴(就是在杭电待了一年多,居然还会在校园里迷路的人,汗~),但是草儿仍然很喜欢旅行,因为在旅途中 会遇见很多人(白马王子,^0^),很多事,还能丰富自己的阅历,还可以看美丽的风景……草儿想去很多地方,她想要去东京铁塔看夜景,去威尼斯看电影,去阳明山上看海芋,去纽约纯粹看雪景,去巴黎喝咖啡写信,去北京探望孟姜女……眼看寒假就快到了,这么一大段时间,可不能浪费啊,一定要给自己好好的放个假,可是也不能荒废了训练啊,所以草儿决定在要在最短的时间去一个自己想去的地方!因为草儿的家在一个小镇上,没有火车经过,所以她只能去邻近的城市坐火车(好可怜啊~)。
 

Input

输入数据有多组,每组的第一行是三个整数T,S和D,表示有T条路,和草儿家相邻的城市的有S个,草儿想去的地方有D个;
接着有T行,每行有三个整数a,b,time,表示a,b城市之间的车程是time小时;(1=<(a,b)<=1000;a,b 之间可能有多条路)
接着的第T+1行有S个数,表示和草儿家相连的城市;
接着的第T+2行有D个数,表示草儿想去地方。
 

Output

输出草儿能去某个喜欢的城市的最短时间。
 

Sample Input

6 2 3 1 3 5 1 4 7 2 8 12 3 8 4 4 9 12 9 10 2 1 2 8 9 10
 

Sample Output

9

须注意重边!!!!!

#include <iostream>
#include <stdio.h>
#include <queue>
#include <algorithm>
#include <string>
#include <string.h>
using namespace std;
#define MAX 1010
#define INF 0x3f3f3f3f

struct Edge
{
    int v,cost;
    Edge(int _v=0,int _cost=0) : v(_v),cost(_cost) {}
};

vector <Edge> E[2*MAX];
bool vis[MAX],loveplace[MAX];;  ///是否在队列中标志
int cnt [MAX];  ///每个点的入队次数
int lowcost[MAX];
int mmin;
queue <int>que;
void addedge(int u,int v,int w){
  E[u].push_back(Edge(v,w));
}
void ini(int n){
    memset(vis,false,sizeof(vis));
    memset(cnt,0,sizeof(cnt));
    while(!que.empty()) que.pop();
    for(int i = 1 ; i<=n ; i++){
        lowcost[i] = INF;
    }
}


///点编号从1开始
bool SPFA(int n,int start)
{
   // cout<<"----------------
";
    ini(n);
    vis[start] = true;
    lowcost[start] = 0;
    cnt[start] = 1;

    que.push(start);

    while(!que.empty()){
        int u = que.front();
        que.pop();
        vis[u] = false;

        for(int i=0 ; i< E[u].size() ; i++){
            int v=E[u][i].v ;
            if( lowcost[v] > lowcost[u] + E[u][i].cost ){
                lowcost[v] = lowcost[u] + E[u][i].cost;
                if(mmin>lowcost[v]&&loveplace[v]) mmin = lowcost[v];
                if(!vis[v]){     ///未出现在队列中
                    vis[v] = true;
                    que.push(v); ///只有到当前点出现更短的路径,并且当前点没有添加到队列中的时候才会添加到队列中再次遍历其孩子
                    if( ++cnt[v] > n ) return false; ///cnt[i] 为入队列次数 ,用来判断是否存在负环回路(原理???)
                }
            }
        }
    }
    return true;
}

int main (){
int T,S,D,n;
int u,v,w,tmp;
int start[MAX];
bool mark = 0;
while(~scanf("%d%d%d",&T,&S,&D)){
    mmin=INF,n=-1;
    memset(loveplace,0,sizeof(loveplace));
    for(int i=1;i<2*MAX;i++) E[i].clear();
   // printf("mmin的初始值为:%d
",mmin);
    for(int i=0;i<T;i++){
       mark = 0;
       scanf("%d%d%d",&u,&v,&w);
       for(int j=0;j<E[u].size();j++){  ///去重边
          if(E[u][j].v == v){
            if(E[u][j].cost > w){
                E[u][j].cost = w , j=E[u].size();
             for(int k = 0 ; k <E[v].size() ; k++)
                if(E[v][j].v == u)
                    E[v][j].cost = w , k = E[v].size();
            }
            mark = 1;
          }
       }
      if(mark == 0){
         addedge(u,v,w);
         addedge(v,u,w);
         if(n<u) n=u;
         if(n<v) n=v;
      }
    }
    for(int i=0;i<S;i++)
        scanf("%d",&start[i]);
    for(int i=0;i<D;i++){
        scanf("%d",&tmp);
        loveplace[tmp]=1;
    }
    for(int i=0;i<S;i++)
       SPFA(n,start[i]);
    printf("%d
",mmin);
}
return 0;
}


原文地址:https://www.cnblogs.com/zswbky/p/5432187.html