题意:草儿有几个想去的地方,要求能去其中一个就好,但是要花最短的时间。并且,草儿要到邻近的城市坐火车去。
思路:我们能建立一张无向图,把草儿家到邻近城市的边权置为 0 即可,这样求出单源最短路径(可以用dijkstra算法),比较草儿想去的几个地方到她家的时间,选一个时间最短的就好。
由于可能存在重边,所以用邻接矩阵来存图较为容易。
代码:
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<stack>
#include<queue>
#include<utility>
#include<vector>
#include<cmath>
#include<set>
#include<map>
#include<iostream>
#include<algorithm>
using namespace std;
const int MAXN = 1010;
const int INF = 1000000;
int T,S,D;
int G[MAXN][MAXN];
int mxctid;
vector<int> wantto;
int d[MAXN];
bool vis[MAXN];
void Dijkstra(int s)
{
for(int i=0; i<=mxctid; i++) d[i] = (i==s? 0:INF);
memset(vis, false, sizeof(vis));
for(int i=0; i<=mxctid; i++){
int x,m = INF;
for(int j=0; j<=mxctid; j++){
if(!vis[j] && d[j]<m)
m = d[x=j];
}
vis[x] = true;
for(int j=0; j<=mxctid; j++){
if(!vis[j] && d[j] > d[x]+G[x][j]){
d[j] = d[x]+G[x][j];
}
}
}
}
void Init()
{
for(int i=0; i<MAXN; i++){
for(int j=0; j<MAXN; j++){
G[i][j] = INF;
}
}
wantto.clear();
mxctid = 0;
}
int main()
{
//freopen("in.txt", "r", stdin);
while(scanf("%d%d%d", &T, &S, &D) == 3){
Init();
while(T--){
int a,b,time;
scanf("%d%d%d", &a, &b, &time);
mxctid = max(mxctid, max(a,b));
G[a][b] = G[b][a] = min(time, G[a][b]);
}
while(S--){
int x;
scanf("%d", &x);
G[0][x] = G[x][0] = 0;
}
while(D--){
int x;
scanf("%d", &x);
wantto.push_back(x);
}
Dijkstra(0);
int ans = INF;
for(int i=0; i<wantto.size(); i++){
ans = min(ans, d[wantto[i]]);
}
printf("%d\n", ans);
}
return 0;
}
用优先权队列实现Dijkstra算法
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<stack>
#include<queue>
#include<utility>
#include<vector>
#include<cmath>
#include<set>
#include<map>
#include<iostream>
#include<algorithm>
using namespace std;
const int MAXN = 1010;
const int INF = 1000000;
struct Node{
int v,w;
Node(){}
Node(int a, int b):v(a),w(b){}
bool operator < (const Node& n)const{
return w>n.w;
}
};
int T,S,D;
int G[MAXN][MAXN];
int mxctid;
vector<int> wantto;
int d[MAXN];
bool vis[MAXN];
void Dijkstra(int s)
{
for(int i=0; i<=mxctid; i++) d[i] = (i==s? 0:INF);
memset(vis, false, sizeof(vis));
priority_queue<Node> que;
que.push(Node(s,d[s]));
while(!que.empty()){
Node node = que.top(); que.pop();
if(vis[node.v]) continue;
vis[node.v] = true;
for(int i=0; i<=mxctid; i++){
if(!vis[i] && d[i]>d[node.v]+G[node.v][i]){
d[i] = d[node.v]+G[node.v][i];
que.push(Node(i, d[i]));
}
}
}
}
void Init()
{
for(int i=0; i<MAXN; i++){
for(int j=0; j<MAXN; j++){
G[i][j] = INF;
}
}
wantto.clear();
mxctid = 0;
}
int main()
{
//freopen("in.txt", "r", stdin);
while(scanf("%d%d%d", &T, &S, &D) == 3){
Init();
while(T--){
int a,b,time;
scanf("%d%d%d", &a, &b, &time);
mxctid = max(mxctid, max(a,b));
G[a][b] = G[b][a] = min(time, G[a][b]); //题目中a,b之间可能有多条路
}
while(S--){
int x;
scanf("%d", &x);
G[0][x] = G[x][0] = 0; //草儿家为 0 位置,到邻近城市时间置为 0
}
while(D--){
int x;
scanf("%d", &x);
wantto.push_back(x);
}
Dijkstra(0);
int ans = INF;
for(int i=0; i<wantto.size(); i++){
ans = min(ans, d[wantto[i]]);
}
printf("%d\n", ans);
}
return 0;
}