1. 程式人生 > >[bzoj3575][最短路-SPFA]道路堵塞

[bzoj3575][最短路-SPFA]道路堵塞

Description

A國有N座城市,依次標為1到N。同時,在這N座城市間有M條單向道路,每條道路的長度是一個正整數。現在,A國
交通部指定了一條從城市1到城市N的路徑,並且保證這條路徑的長度是所有從城市1到城市N的路徑中最短的。不幸
的是,因為從城市1到城市N旅行的人越來越多,這條由交通部指定的路徑經常發生堵塞。現在A國想知道,這條路
徑中的任意一條道路無法通行時,由城市1到N的最短路徑長度是多少。

Input

第一行是三個用空格分開的正整數N、M和L,分別表示城市數目、單向道路數目和交通部指定的最短路徑包含多少條道路。
按下來M行,每行三個用空格分開的整數a、b和c,表示存在一條由城市a到城市b的長度為c的單向道路。
這M行的行號也是對應道路的編號,即其中第1行對應的道路編號為1,第2行對應的道路編號為2,…,第M行對應的道路編號為M。
最後一行為L個用空格分開的整數sp(1)…,,sp(L),依次表示從城市1到城市N的由交通部指定的最短路徑上的道路的編號。
2<N<100000,1<M<200000。所用道路長度大於0小於10000。

Output

L行,每行為一個整數,第i行(i=1,2…,,L)的整數表示刪去編號為sp(i)的道路後從城市1到城市N的最短路徑長度。
如果去掉後沒有從城市1到城市N的路徑,則輸出一1。

Sample Input

4 5 2

1 2 2

1 3 2

3 4 4

3 2 1

2 4 3

1 5

Sample Output

6

6

題解

首先有一個性質
刪去一條邊之後走的邊一定是
1走一些最短路邊 然後走一些非最短路邊 然後再走一堆最短路邊到n
根據這個就可以搞事了
不妨先把所有最短路邊刪掉
列舉每條邊依次加入可以跑的邊中 每次就讓當前這條邊去跑spfa
比較好玩的就是這個dis不需要清空,一清空就穩的 n

2 n^2 了啊
因為你發現dis是單調不增的,所以完全可以直接在上面的基礎跑
如果走到了一些在最短路上的點,就把當前這條路徑扔進堆裡,順便記錄一下最後沒有跑的最短路邊是哪一條
然後掃一遍就完事

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include
<cmath>
#include<queue> #include<vector> #include<ctime> #include<map> #include<bitset> #define LL long long #define mp(x,y) make_pair(x,y) #define pll pair<long long,long long> #define pii pair<int,int> using namespace std; inline int read() { int f=1,x=0;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} return x*f; } int stack[20]; inline void write(int x) { if(x<0){putchar('-');x=-x;} if(!x){putchar('0');return;} int top=0; while(x)stack[++top]=x%10,x/=10; while(top)putchar(stack[top--]+'0'); } inline void pr1(int x){write(x);putchar(' ');} inline void pr2(int x){write(x);putchar('\n');} const int MAXM=200005; const int MAXN=100005; struct node{int x,y,c,next;}a[MAXM];int len,last[MAXN]; void ins(int x,int y,int c){len++;a[len].x=x;a[len].y=y;a[len].c=c;a[len].next=last[x];last[x]=len;} int d[MAXN],n,m,L; queue<int> li; priority_queue<pii,vector<pii>,greater<pii> > heap; bool is[MAXN],vis[MAXN],no[MAXM]; int fr[MAXN],ba[MAXN],lin[MAXM],s[MAXM],pre[MAXN],tot; void spfa(int st) { li.push(st); while(!li.empty()) { int x=li.front();li.pop();vis[x]=false; for(int k=last[x];k;k=a[k].next) { int y=a[k].y; if(d[y]>d[x]+a[k].c&&(!no[k])) { d[y]=d[x]+a[k].c; if(is[y]) { heap.push(mp(d[y]+ba[y],pre[y])); // printf("YES %d %d %d %d %d\n",st,x,y,d[y]+ba[y],pre[y]); } if(!vis[y])vis[y]=true,li.push(y); } } } } int main() { // freopen("1.in","r",stdin); n=read();m=read();L=read(); for(int i=1;i<=m;i++) { int x=read(),y=read(),c=read(); ins(x,y,c); } for(int i=1;i<=L;i++) { no[lin[i]=read()]=true; s[++tot]=a[lin[i]].x;is[s[tot]]=true; fr[a[lin[i]].y]=fr[s[tot]]+a[lin[i]].c; pre[a[lin[i]].y]=i; } s[++tot]=n;is[s[tot]]=true; for(int i=L;i>=1;i--)ba[s[i]]=ba[s[i+1]]+a[lin[i]].c; // for(int i=1;i<=tot;i++)printf("%d ",s[i]); // puts(""); memset(d,63,sizeof(d));d[1]=0; spfa(1); for(int i=1;i<=L;i++) { while(heap.size()&&heap.top().second<i)heap.pop(); if(!heap.size())puts("-1"); else pr2(heap.top().first); no[i]=false; d[s[i+1]]=d[s[i]]+a[lin[i]].c; spfa(s[i+1]); } return 0; }