TYZ 8/23 物语

题目描述:

3、物语

(monogatari.cpp/c/pas)

 

【问题描述】

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

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

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

 

【输入格式】

第一行三个整数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条道路的通过时间。

 

【输出格式】

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

 

【样例输入1】

4 5 4

1 2 7

1 3 4

2 4 3

3 4 6

2 3

1

2

4

6

 

【样例输出1】

8

9

10

10


【样例说明1】

如图1,红色的圆圈表示少年和IA的出发地,绿色的圆圈表示目的地,连线表示道路,旁边的数字表示通过该道路的时间。最后一条道路时间未知用x表示。图中不重复经过同一区域的路径有4条,分别为1→2→4,1→3→4,1→2→3→4,1→3→2→4,其所需时间随x的关系如下表所示:

可以证明,不存在更优的解,故将上表最后一列输出。

 

【样例输入2】

4 3 1

1 2 7

1 3 4

2 3

9

【样例输出2】

+Inf

 

【样例说明2】

    如图2,起点和终点不连通,故少年和IA无法逃离部落。

 

【数据范围】

 

测试点编号

N

M

K

其他

1

N = 2

M = 1

K = 1

随机生成

2

N = 5

M = 4

K = 1

随机生成

3

N = 5

M = 10

K = 5

随机生成

4

N = 50

M = 100

K = 10

随机生成

5

N = 75

M = 200

K = 10

随机生成

6

N = 100

M = 1000

K = 10

随机生成

7

N = 200

M = 2000

K = 10

随机生成

8

N = 300

M = 3000

K = 10

随机生成

9

N = 1000

M = 30 000

K = 10

随机生成

10

N = 2000

M = 50 000

K = 10

随机生成

11

N = 10 000

M = 200 000

K = 10

随机生成

12

N = 30 000

M = 300 000

K = 10

随机生成

13

N = 50 000

M = 300 000

K = 30 000

随机生成

14

N = 100 000

M = 500 000

K = 30 000

随机生成

15

N = 100 000

M = 500 000

K = 30 000

随机生成

16

N = 120 000

M = 179 998

K = 10

N/A

17

N = 180 000

M = 299 997

K = 10

N/A

18

N = 180 000

M = 269 998

K = 10

N/A

19

N = 180 000

M = 419 991

K = 30 000

N/A

20

N = 200 000

M = 399 996

K = 30 000

N/A

这个题我时暴力SPFA的,25/100

但是实际上有好多优化可以写

最后发现,不用重复的计算最短路

平时SPFA,只计算点对点的距离

然而一个点,到其他所有的点的距离都计算出来了

为何不把最后一条边弄出来。单独地算一下1到其他所有点的距离和N到其他所有点的距离

当这条边加进去,比较一下最短路有没有变化

比TYZ 8/23 T2简单多了

代码

#include<iostream>
#include<cstring>
#include<queue>
#include<algorithm>
#include<cstdio>
#include<vector>
#include<limits.h>
using namespace std;
const int maxn=180005;
typedef long long ll;
struct edge{
	ll to,v;
};
vector<edge> g[maxn];
ll t1,t2,t3;
ll n,m,k;
void git(ll &xxx)
{
	xxx=0;
	char ch=getchar();
	while(ch<'0'||ch>'9')
	ch=getchar();
	while(ch>='0'&&ch<='9')
	{
		xxx=xxx*10+ch-'0';
		ch=getchar();
	}
}
edge kong;
ll mos,moe;
ll kc[30005];
ll d[maxn];
ll inf=INT_MAX;
bool book[maxn];
queue<ll> q;
void spfa(ll s)
{
	for(int i=0;i<=n;i++)
		{
		d[i]=inf;
		book[i]=0;
	    }
		book[s]=1;
		d[s]=0;
		q.push(s);
		while(!q.empty())
		{
			
			ll nw=q.front();
			ll lm=g[nw].size();
			for(int i=0;i<lm;i++)
			{
				edge u=g[nw][i];
				if(d[u.to]>d[nw]+u.v)
				{
					d[u.to]=d[nw]+u.v;
					if(!book[u.to])
					{
						book[u.to]=1;
						q.push(u.to);
					}
				}
			}
			book[nw]=0;
			q.pop();
		}
}
ll d1[maxn];
int main()
{
	freopen("monogatari.in","r",stdin);
	freopen("monogatari.out","w",stdout);
	cin>>n>>m>>k;
	for(int i=1;i<m;i++)
	{
		git(t1);git(t2);git(t3);
		edge nw=kong;
		nw.to=t2;
        nw.v=t3;
        g[t1].push_back(nw);
        nw.to=t1;
        g[t2].push_back(nw);
	}
	spfa(1);
	for(int i=0;i<=n;i++)
	d1[i]=d[i];
	spfa(n);
	git(mos);git(moe);
	for(int i=1;i<=k;i++)
	{
		git(kc[i]);
		ll na=min(d1[mos]+d[moe],d1[moe]+d[mos])+kc[i];
		ll nb=d1[n];
		ll ans=min(na,nb);
		if(ans==inf)
		cout<<"+Inf\n";
		else
		cout<<ans<<"\n";
	}
	return 0;
}


 


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值