【bzoj3575】 Hnoi2014—道路堵塞
http://www.lydsy.com/JudgeOnline/problem.php?id=3575 (题目链接)
题意
给出一个有向图和一条最短路,问最短路上任意一条边断掉,此时的最短路是多少。
Solution
听说这道题正解被江哥插了。。。右转题解→_→:lmy学长
平衡树用堆就可以了。
细节
用栈来存要加入堆中的点,不然不好消除标记。
代码
// bzoj3575 #include<algorithm> #include<iostream> #include<cstdlib> #include<cstring> #include<cstdio> #include<cmath> #include<queue> #define LL long long #define inf (1ll<<60) #define Pi acos(-1.0) #define free(a) freopen(a".in","r",stdin),freopen(a".out","w",stdout); using namespace std; const int maxn=200010; int head[maxn],dis[maxn],vis[maxn],st[maxn],in[maxn]; int n,m,L,cnt,id[maxn],ord[maxn],suf[maxn]; struct edge {int from,to,next,w;}e[maxn<<1]; struct data { int num,len; friend bool operator < (const data a,const data b) { return a.len>b.len; } }; priority_queue<data> T; inline void link(int u,int v,int w) { e[++cnt]=(edge){u,v,head[u],w};head[u]=cnt; } inline void SPFA(int u,int v,int k) { queue<int> q;q.push(u); int top=0; while (!q.empty()) { int x=q.front();q.pop(); vis[x]=0; for (int i=head[x];i;i=e[i].next) if (i!=k) { if (ord[e[i].to]>ord[u]) { dis[e[i].to]=min(dis[e[i].to],dis[x]+e[i].w); if (!in[e[i].to]) in[e[i].to]=1,st[++top]=e[i].to; } else if (dis[e[i].to]>dis[x]+e[i].w) { dis[e[i].to]=dis[x]+e[i].w; if (!vis[e[i].to]) vis[e[i].to]=1,q.push(e[i].to); } } } for (int i=1;i<=top;i++) { T.push((data){ord[st[i]],suf[st[i]]+dis[st[i]]}); in[st[i]]=0; } } int main() { scanf("%d%d%d",&n,&m,&L); for (int u,v,w,i=1;i<=m;i++) { scanf("%d%d%d",&u,&v,&w); link(u,v,w); } ord[1]=1; for (int i=1;i<=L;i++) scanf("%d",&id[i]),ord[e[id[i]].to]=i+1; for (int i=L;i>=1;i--) suf[e[id[i]].from]=suf[e[id[i]].to]+e[id[i]].w; memset(dis,0x7f,sizeof(dis));dis[1]=0; for (int i=1;i<=L;i++) { int u=e[id[i]].from,v=e[id[i]].to; SPFA(u,v,id[i]); while (!T.empty() && T.top().num<ord[v]) T.pop(); printf("%d\n",T.empty() ? -1 : T.top().len); dis[v]=dis[u]+e[id[i]].w; } return 0; }
This passage is made by MashiroSky.