旅行二 (数据结构作业)

算法与数据结构实验题 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;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值