物语(monogatari)

\(Description\)

某一天,少年邂逅了同病相连的IA。见面后,IA一把牵起少年的手,决定和他一起逃离部落,离开这个无法容身的是非之地。

要逃离部落,少年和IA就需要先选择一条耗时最少的路线,从而避免被部落的大人们抓到。部落可以大致分为N个区域,少年和IA在区域1,部落的出口设在区域N。此外部落还有M条连接两个区域道路。道路是无向的,没有一条道路的两端连接相同的区域,也没有两条道路所连接的两个区域完全相同。对于其中前(M−1)条道路,其通过时间是确定的,但最后一条道路,由于地理因素,通过其的时间会不断变化。

现在,少年和IA得知了在K个不同的时段里,通过第M条道路的时间,请您分别计算出在这K 个时段中逃离部落的最少时间,以帮助他们确定行动的时刻。

\(Input\)

第一行三个整数N,M,K,分别表示区域数,道路数,询问数。

接下来M−1行每行三个整数 \(ui,vi,wi(ui≠vi,1≤ui,vi≤N,0<wi≤10^9)\),表示这条道路连接的区域和通过时间。

紧接着是两个整数 \(ui,vi(ui≠vi,1≤ui,vi≤N)\),表示第M条道路连接的区域。

最后K行,每行一个正整数 \(xi(0<xi≤10^9)\),表示目前第M条道路的通过时间。

\(Output\)

输出共计K行,每行一个整数,表示对应时段逃离部落的最短时间。如果在该时段内无法逃离,输出“+Inf”。

\(Sample Input\)

输入1:

4 5 4

1 2 7

1 3 4

2 4 3

3 4 6

2 3

1

2

4

6

输入2:

4 3 1

1 2 7

1 3 4

2 3

9

\(Sample Output\)

输出1:

8

9

10

10

输出2:

+Inf

Hint

代码(常数巨大,不得不开O)

#pragma GCC optimize(2)
#include<cstdio>
#include<queue>
#include<cstring>
using namespace std;
typedef long long LL;

const int N = 200000 , M = 500000;
const LL INF = 1e16 + 10;
int n , m , k , h[N + 5] , vis[N + 5] , tot = 1 , u , v;
LL dis1[N + 5] , disu[N + 5] , disv[N + 5] , ans , w;

struct edge{
	int to , nxt;
	LL w;
}e[(M << 1) + 5];
struct node{
	int id;
	LL d;
	bool operator < (node c) const
	{
		return d > c.d;
	}
};

inline void add(int u , int v , int w)
{
	e[++tot].to = v , e[tot].w = w , e[tot].nxt = h[u] , h[u] = tot;
}

inline LL Min(LL x , LL y) { return x < y ? x : y; };

priority_queue<node> q;

inline void dij1()
{
	memset(vis , 0 , sizeof(vis));
	dis1[1] = 0;
	q.push((node){1 , 0});
	while (!q.empty())
	{
		node x = q.top();
		q.pop();
		if (vis[x.id]) continue;
		vis[x.id] = 1;
		for(register int i = h[x.id]; i; i = e[i].nxt)
		{
			if (dis1[x.id] + e[i].w < dis1[e[i].to])
			{
				dis1[e[i].to] = dis1[x.id] + e[i].w;
				q.push((node){e[i].to , dis1[e[i].to]});
			}
		}
	}
}

priority_queue<node> Q;

inline void diju()
{
	memset(vis , 0 , sizeof(vis));
	disu[u] = 0;
	Q.push((node){u , 0});
	while (!Q.empty())
	{
		node x = Q.top();
		Q.pop();
		if (vis[x.id]) continue;
		vis[x.id] = 1;
		for(register int i = h[x.id]; i; i = e[i].nxt)
		{
			if (disu[x.id] + e[i].w < disu[e[i].to])
			{
				disu[e[i].to] = disu[x.id] + e[i].w;
				Q.push((node){e[i].to , disu[e[i].to]});
			}
		}
	}
}

priority_queue<node> QQ;

inline void dijv()
{
	memset(vis , 0 , sizeof(vis));
	disv[v] = 0;
	QQ.push((node){v , 0});
	while (!QQ.empty())
	{
		node x = QQ.top();
		QQ.pop();
		if (vis[x.id]) continue;
		vis[x.id] = 1;
		for(register int i = h[x.id]; i; i = e[i].nxt)
		{
			if (disv[x.id] + e[i].w < disv[e[i].to])
			{
				disv[e[i].to] = disv[x.id] + e[i].w;
				QQ.push((node){e[i].to , disv[e[i].to]});
			}
		}
	}
}

int main()
{
	freopen("monogatari.in" , "r" , stdin);
	freopen("monogatari.out" , "w" , stdout);
	scanf("%d%d%d" , &n , &m , &k);
	for(register int i = 1; i < m; i++) 
	{
		scanf("%d%d%lld" , &u , &v , &w);
		add(u , v , w) , add(v , u , w);	
	}
	for(register int i = 1; i <= n; i++)
		dis1[i] = INF , disu[i] = INF , disv[i] = INF;
	scanf("%d%d" , &u , &v);
	dij1() , diju() , dijv();
	for(register int i = 1; i <= k; i++)
	{
		scanf("%lld" , &w);
		ans = dis1[n];
		if (dis1[u] != INF && disv[n] != INF) ans = Min(ans , dis1[u] + w + disv[n]);
		if (dis1[v] != INF && disu[n] != INF) ans = Min(ans , dis1[v] + w + disu[n]);
		if (ans == INF) printf("+Inf\n");
		else printf("%lld\n" , ans);
	}
}
posted @ 2020-02-16 22:26  leiyuanze  阅读(632)  评论(0)    收藏  举报