FZU-2261-浪里个浪(dijkstra小窍门)

FZU-2261-浪里个浪

Problem Description

有n个城市,m条交通路径,每条交通路径都是单行道。他已经预先规划好了一些点作为旅游的起点和终点,他想选择其中一个起点和一个终点,并找出从起点到终点的一条路线亲身体验浪的过程。但是他时间有限,所以想选择耗时最小的,你能告诉他最小的耗时是多少吗?

Input

包含多组测试数据。

输入第一行包括两个整数n和m,表示有n个地点,m条可行路径。点的编号为1 - n。

接下来m行每行包括三个整数i, j, cost,表示从地点i到地点j需要耗时cost。

接下来一行第一个数为S,表示可能的起点数,之后S个数,表示可能的起点。

接下来一行第一个数为E,表示可能的终点数,之后E个数,表示可能的终点。

0<S, E≤n≤100000,0<m≤100000,0<cost≤100。

Output

输出他需要的最短耗时。

Sample Input

4 4
1 3 1
1 4 2
2 3 3
2 4 4
2 1 2
2 3 4

Sample Output

1


这一题的只比裸dijkstra多了一个---把图存完后,给出S个可能的起点,E个可能的终点,从中选出一个起点和终点,使得路径最短。

就是一个小敲门

把 0 作为超级源点, n+1 作为超级终点 ,

每个可能的起点与0相连,权值为0,

每个可能的终点与 n+1 相连,权值为0,

直接dijkstra。

输出 dis[ n+1 ]~~~~~~

#include <iostream>
#include <algorithm>
#include <vector>
#include <queue>
#include <cstring>
#include <cstdio>

using namespace std;

typedef pair<int, int> P;  //first是最短距离,second 是顶点的编号

const int maxn = 100010;
const int INF = 0x3f3f3f3f;

struct Edge
{
	int to,val;
};

int N;
int dis[maxn];     //记录各个点到源点的距离
vector<Edge> G[maxn]; // vector 存图,比如G[2] 后面存的是 与 点 2 有联系的点 和 权值。

void dijkstra(int s)   //s 是源点
{
	// que  是一个pair<>类型的优先队列
	priority_queue<P, vector<P>, greater<P> > que; //通过指定greater<P>参数,堆按照first从小到大的顺序取出值
	memset(dis,INF,sizeof(dis));
	dis[s] = 0;               // 源点到源点的距离为0
	que.push(P(0,s));      //先把源点放入队列,从源点来时操作

	while(!que.empty()) //当队列不为空时
	{
		P T = que.top();   //q.top(). first 就是离源点最近的点,用 T 记录下来
		que.pop();         // 记录下来之后,q.top()可以出队了、
		int a = T.second; //当前离源点最近的点的编号

		if(dis[a] != T.first)
			continue;
		for(int i = 0;i < G[a].size();i ++)
		{
			Edge e = G[a][i]; //  G[a][i] 存的是a 点的一个出边 有 to 和 val 两个值。
			if(dis[e.to] > dis[a] + e.val)
			{
				dis[e.to] = dis[a] + e.val;
				que.push(P(dis[e.to],e.to));
			}

		}

	}

}
int y1[1000000];
int main()
{
	int n,m;
	int x,y; //x个起点,y个终点
	int a;
	Edge b;
	while(scanf("%d %d",&n,&m)!=EOF)
	{
		for(int i = 0;i < m;i ++)
		{
			scanf("%d %d %d",&a,&b.to,&b.val);
			G[a].push_back(b);
		}
		scanf("%d",&x);
		for(int i = 0;i < x;i ++) //把 0 作为超级源点
		{
			scanf("%d",&b.to);
			b.val = 0;
			G[0].push_back(b);
		}
		scanf("%d",&y);
		b.to = n+1;
		b.val = 0;
		for(int i = 0;i < y;i ++) //把 n + 1 作为超级终点。 
		{
			int end; 
			scanf("%d",&end);
			G[end].push_back(b);
			
		}
		dijkstra(0);
		cout<<dis[n+1]<<endl;
        for(int i = 0;i <= n;i ++)
            G[i].clear();
	}
		return 0;
 }

猜你喜欢

转载自blog.csdn.net/qq_41003528/article/details/80200647
今日推荐