算法与数据结构实验题 7.3 旅行二
★实验任务
王尼玛又想出去旅游了,由于王尼玛是个抠门的人,所以王尼玛想要花最少的钱去一个自 己想去的地方。王尼玛决定使用火车去旅行,地图上总共有 n 个城市,其中有 k 个城市是王尼玛想去玩的城市。由于王尼玛天天为公司加班加点,公司决定奖励他,免费送他去其中的
m 个城市(也就是说王尼玛能选择这 m 个城市中的一个作起点)。王尼玛数学不好,让你帮他选一条花费最少的路,这条路最终能到某一个他喜欢的城市。
★数据输入
第一行有四个整数 n,T,m 和 k,表示有 n 个城市和 T 条路,公司奖励王尼玛其中 m 个城市,王尼玛喜欢其中的 k 个城市。接下来有 T 行,每行有三个整数 a,b,c,表示 a 城市和 b 城市火车通行的花费(火车通行是双向的),接下来一行有 m 个整数,表示公司奖励的 m 个城市的编号。最后一行有 k 个整数,表示王尼玛喜欢的 k 个城市的编号。( 1<=a,b<=n , 0<=c<=10000 , 2<=n<=50000,1<=T<=200000, 1<=m,k<=n ,数据保证王尼玛一
定能到喜欢的城市)
★数据输出
每个样例输出一行,输出王尼玛能去某个喜欢的城市的最短花费。
输入示例 | 输出示例 |
10 6 2 3 | 9 |
1 3 5 |
|
1 4 7 |
|
2 8 12 |
|
3 8 4 |
|
4 9 12 |
|
9 10 2 |
|
1 2 |
|
8 9 10 |
|
解题思路:
和前两天博客文章(一个人的旅行)简直一摸一样。
把奖励的城市连接起来,并设置为边权为0.
#include <cstdio>
#include <map>
#include <vector>
#include <queue>
#include <algorithm>
using namespace std;
const int INF=1<<29;
int k[50010],m[50010];
map <int,int> mp[50010];
struct G{
vector <int> adj;
}g[50010];
struct cmp
{
bool operator()(const pair <long long,int> p1, const pair <long long,int> p2)
{
return p1.first > p2.first; //first的小值优先
}
};
void Dijkstra (int n,int kn,int mn)
{
long long dis[50010];
int vis[50010]={0};
pair <long long,int> p;
priority_queue <pair <long long,int> ,vector<pair<long long,int> > ,cmp > q;
for (int i=1;i<=n+1;i++)
{
dis[i]=INF;
}
for (int i=1;i<=mn;i++)
{
dis[m[i]]=0;
p.first=dis[m[i]];
p.second=m[i];
q.push(p);
}
vector <int> :: iterator it;
while (!q.empty())
{
int v=q.top().second;
q.pop();
if (vis[v]==1)
continue;
vis[v]=1;
for (it=g[v].adj.begin();it!=g[v].adj.end();it++)
{
if (vis[*it]==0 && dis[*it] > dis[v] + mp[*it][v])
{
dis[*it] = dis[v] + mp[*it][v];
p.first=dis[*it];
p.second=*it;
q.push(p);
}
}
}
long long ans=INF;
for (int i=1;i<=kn;i++)
{
ans=min(ans,dis[k[i]]);
}
printf ("%lld\n",ans);
}
int main()
{
int n,mn,t,kn,a,b,c;
bool flag=false;
scanf ("%d%d%d%d",&n,&t,&mn,&kn);
for (int i=0;i<t;i++)
{
scanf ("%d%d%d",&a,&b,&c);
g[a].adj.push_back(b);
g[b].adj.push_back(a);
mp[a][b]=c;
mp[b][a]=c;
}
for (int i=1;i<=mn;i++)
{
scanf ("%d",&m[i]);
}
for (int i=1;i<=kn;i++)
{
scanf ("%d",&k[i]);
}
Dijkstra(n,kn,mn);
return 0;
}
修改:
删去去重语句,权值改为vector储存。
#include <cstdio>
#include <map>
#include <vector>
#include <queue>
#include <algorithm>
using namespace std;
const int INF=1<<29;
struct G{
vector <int> adj;
vector <int> w;
}g[50010];
struct cmp
{
bool operator()(const pair <long long,int> p1, const pair <long long,int> p2)
{
return p1.first > p2.first; //first的小值优先
}
};
long long dis[50010];
int vis[50010];
void Dijkstra (int n)
{
pair <long long,int> p;
priority_queue <pair <long long,int> ,vector<pair<long long,int> > ,cmp > q;
for (int i=0;i<=n+1;i++)
dis[i]=INF;
dis[0]=0;
p.first=dis[0];
p.second=0;
q.push(p);
vector <int> :: iterator it;
while (!q.empty())
{
p=q.top();
q.pop();
int v=p.second;
if (vis[v]==1)
continue;
vis[v]=1;
for (it=g[v].adj.begin();it!=g[v].adj.end();it++)
{
if (vis[*it]==0 && dis[*it] > dis[v] + g[v].w[it-g[v].adj.begin()])
{
dis[*it] = dis[v] + g[v].w[it-g[v].adj.begin()];
p.first=dis[*it];
p.second=*it;
q.push(p);
}
}
}
printf ("%lld\n",dis[n+1]);
}
int main()
{
int n,mn,t,kn,a,b,c;
bool flag=false;
scanf ("%d%d%d%d",&n,&t,&mn,&kn);
for (int i=0;i<t;i++)
{
scanf ("%d%d%d",&a,&b,&c);
g[a].adj.push_back(b);
g[b].adj.push_back(a);
g[a].w.push_back(c);
g[b].w.push_back(c);
}
for (int i=1;i<=mn;i++)
{
scanf ("%d",&a);
g[0].adj.push_back(a);
g[a].adj.push_back(0);
g[a].w.push_back(0);
g[0].w.push_back(0);
}
for (int i=1;i<=kn;i++)
{
scanf ("%d",&a);
g[n+1].adj.push_back(a);
g[a].adj.push_back(n+1);
g[a].w.push_back(0);
g[n+1].w.push_back(0);
}
Dijkstra(n);
return 0;
}