1. 程式人生 > >2261 ] 浪裡個浪(spfa)

2261 ] 浪裡個浪(spfa)

TonyY是一個喜歡到處浪的男人,他的夢想是帶著蘭蘭姐姐浪遍天朝的各個角落,不過在此之前,他需要做好規劃。

現在他的手上有一份天朝地圖,上面有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

思路:

        要確定起點和終點,不用kruskal  用spfa

        另外因為起點、終點不確定,所以在所有起點前加一個0節點作為公共起點,在所有終點後加一個n+1節點作為公共終點

        然後直接套模板

Code:

#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<queue>
#include<stack>
using namespace std;
const int MAXN=2e5+10;
const int INF=0x3f3f3f3f;
int n,m,f,t,v,tot,ans;
int dis[MAXN],vis[MAXN],head[MAXN];
struct edge
{
	int to,w,next;
}edge[MAXN];
void build(int u,int v,int w)
{
	edge[tot].to=v;
	edge[tot].w=w;
	edge[tot].next=head[u];
	head[u]=tot++;
}

void spfa()
{
	queue <int> q;
	q.push(0);
	vis[0]=1;
	dis[0]=0;
	while(!q.empty())
	{
		int u=q.front();
		q.pop();
		vis[u]=0;
		if(u==n+1)
		{
			ans=min(ans,dis[u]);
			continue;
		}
		for(int i=head[u];i!=-1;i=edge[i].next)
		{
			int v=edge[i].to,w=edge[i].w;
			if(dis[v]>dis[u]+w)
			{
				dis[v]=dis[u]+w;
				if(vis[v]==0)
				{
					q.push(v);
					vis[v]=1;
				}
			}
		}
	}
}
int main()
{
	while(~scanf("%d%d",&n,&m))
	{
		int a,x;
		tot=0;
		ans=INF;
		memset(dis,INF,sizeof(dis));
		memset(vis,0,sizeof(vis));
		memset(head,-1,sizeof(head));
		for(int i=1;i<=m;i++)
		{
			scanf("%d%d%d",&f,&t,&v);
			build(f,t,v);
		}
		scanf("%d",&a);
		for(int i=1;i<=a;i++)
		{
			scanf("%d",&x);
			build(0,x,0);
		}
		scanf("%d",&a);
		for(int i=1;i<=a;i++)
		{
			scanf("%d",&x);
			build(x,n+1,0);
		}
		spfa();
		printf("%d\n",ans);
	}
return 0;
}