物語--解題報告
【問題描述】
某一天,少年邂逅了同病相連的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 |
【題解】
首先把第M個邊去掉求最短路,分別求出1到任何一個點的最短路,以及任何一個點到N的最短路(反向spfa)。
然後當第M個邊(S,T)的長度變化的時候,只需要比較dis[1][S]+bian[S][T]+dis[T][N],dis[1][N]即可。
程式碼附上
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cstring>
#include<ctime>
#include<queue>
#define MAXN 200005
#define MAXM 500005
#define INF 4611686010000000000LL
#define pr pair<LL, int>
#define mp make_pair
#define x first
#define y second
using namespace std ;
typedef long long LL ;
struct road
{
int x, next ;
LL dis ;
} r[MAXM*2] ;
int n,m,k;
int ST,ED;
LL S[MAXN],T[MAXN];
int st[MAXN],w,vis[MAXN] ;
priority_queue<pr>q;
void add(int x,int y,LL dis)
{
r[++w].x=y;
r[w].next=st[x] ;
r[w].dis=dis;
st[x]=w ;
}
void spfa(int x)
{
int tmp;
LL now;
for(int i=1;i<=n;i++)
T[i] = INF ;
T[x]=0;
q.push(mp(0,x)) ;
while(!q.empty())
{
x=q.top().y;
now=q.top().x;
q.pop() ;
if(-now>T[x])
continue ;
now=-now ;
for(int i=st[x];i;i=r[i].next)
if(T[tmp=r[i].x]>T[x]+r[i].dis)
{
T[tmp]=T[x]+r[i].dis ;
q.push(mp(-T[tmp],tmp)) ;
}
}
}
int main()
{
int fr,to;
LL dt,tmp;
scanf("%d%d%d",&n,&m,&k) ;
for(int i=1,tmp=0;i<m;i++)
{
scanf("%d%d%I64d",&fr,&to,&dt) ;
tmp+=dt;
add(fr,to,dt),add(to,fr,dt) ;
}
scanf("%d%d",&ST,&ED);
spfa(1);//正向
memcpy(S,T,sizeof(S)) ;
spfa(n);//反向
for(int i=1;i<=k;i++)
{
scanf("%I64d",&dt) ;
tmp=min(S[n],min(S[ST]+T[ED],S[ED]+T[ST])+dt);
if(tmp==INF)
printf("+Inf\n") ;
else printf("%I64d\n", tmp) ;
}
}