BZOJ.3575.[HNOI2014]道路堵塞(最短路 動態SPFA)
阿新 • • 發佈:2018-10-18
-i 否則 online 所有 ati ++i 當前 set mat 處的值可以更新所有\(y\)之前最短路的邊的\(Ans\)。
我們用堆把這個值及\(y\)前面那條最短路的邊的標號\(id\)存下來。如果當前刪的邊\(i\)大於等於堆頂的\(id\),就可以直接用堆頂的答案了。否則直接\(pop\)掉堆頂。
所以我們把所有最短路邊刪掉,每求完一條邊\((u,v)\)的值時更新\(dis[v]\),然後把\(v\)再加入隊列SPFA就行了。
每次SPFA不需要清空\(dis\),\(dis\)是遞減的。
題目鏈接
\(Description\)
給你一張有向圖及一條\(1\)到\(n\)的最短路。對這條最短路上的每條邊,求刪掉這條邊後\(1\)到\(n\)的最短路是多少。
\(Solution\)
枚舉刪每條邊然後求最短路顯然不行。考慮怎麽保留之前求最短路的一些信息。
考慮刪掉一條邊後的最短路,\(1\)沿最短路到了某個點\(x\),然後如果\(x\)到了最短路上的某點\(y\),之後一定是沿\(y\)到\(n\)的最短路走到\(n\)。
\(n\)也是最短路上的點,即\(x\)一定會到達某個\(y\)並沿最短路到達\(n\)。這時就可以在\(y\)處直接更新\(Ans\)。
我們發現在\(y\)
我們用堆把這個值及\(y\)前面那條最短路的邊的標號\(id\)存下來。如果當前刪的邊\(i\)大於等於堆頂的\(id\),就可以直接用堆頂的答案了。否則直接\(pop\)掉堆頂。
所以我們把所有最短路邊刪掉,每求完一條邊\((u,v)\)的值時更新\(dis[v]\),然後把\(v\)再加入隊列SPFA就行了。
每次SPFA不需要清空\(dis\),\(dis\)是遞減的。
當然本題復雜度玄學。
//18720kb 3244ms #include <queue> #include <cstdio> #include <cctype> #include <cstring> #include <algorithm> //#define gc() getchar() #define MAXIN 200000 #define gc() (SS==TT&&(TT=(SS=IN)+fread(IN,1,MAXIN,stdin),SS==TT)?EOF:*SS++) typedef long long LL; const int N=1e5+5,M=2e5+5; int Enum,H[N],nxt[M],fr[M],to[M],len[M],dis[N],dt[N],A[N],pre[N]; bool ban[M]; char IN[MAXIN],*SS=IN,*TT=IN; struct Node { int pos,val; bool operator <(const Node &x)const { return val>x.val; } }; std::priority_queue<Node> hp; inline int read() { int now=0;register char c=gc(); for(;!isdigit(c);c=gc()); for(;isdigit(c);now=now*10+c-'0',c=gc()); return now; } inline void AE(int w,int v,int u) { to[++Enum]=v, fr[Enum]=u, nxt[Enum]=H[u], H[u]=Enum, len[Enum]=w; } void SPFA(int s) { static bool inq[N]; static std::queue<int> q; q.push(s); while(!q.empty()) { int x=q.front(); q.pop(); inq[x]=0; for(int i=H[x],v; i; i=nxt[i]) if(!ban[i]&&dis[v=to[i]]>dis[x]+len[i]) { dis[v]=dis[x]+len[i]; if(pre[v]) hp.push((Node){pre[v],dis[v]+dt[pre[v]]}); else if(!inq[v]) inq[v]=1, q.push(v); } } } int main() { int n=read(),m=read(),l=read(); for(int i=1; i<=m; ++i) AE(read(),read(),read()); for(int i=1,id; i<=l; ++i) { A[i]=id=read(); ban[id]=1, pre[to[id]]=i; } for(int i=l-1; i; --i) dt[i]=dt[i+1]+len[A[i+1]]; memset(dis,0x3f,sizeof dis); dis[1]=0, SPFA(1); for(int i=1,id; i<=l; ++i) { while(!hp.empty()&&hp.top().pos<i) hp.pop(); if(hp.empty()) puts("-1"); else printf("%d\n",hp.top().val); id=A[i], dis[to[id]]=dis[fr[id]]+len[id]; SPFA(to[id]); } return 0; }
BZOJ.3575.[HNOI2014]道路堵塞(最短路 動態SPFA)