题目描述:
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,只计算点对点的距离
然而一个点,到其他所有的点的距离都计算出来了
为何不把最后一条边弄出来。单独地算一下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;
}