首先我们玩一下会发现删掉一条路之后的最短路一定是原来最短路的一段且仅一段换成了一条非最短路
每一次删边,我们从边的起点出发进行spfa,当spfa到终点往后的最短路上的点时更新一下答案(的集合)
对于答案的集合呢,我们维护以每个点为终点的非最短路的总的长度(即1-p最短路+某个点->p的非最短路+p->n的最短路),这个搞个线段树就好了
然后处理完一条边之后,以这条边的终点为终点的答案全都非法了,线段树上删一删就好了
(然后就TM跑了10S,卡着时限过了,业界毒瘤VFK!)
<span style="font-size:18px;">#include<iostream> #include<cstdio> #include<cstring> #include<queue> using namespace std; const int N=100000+5; const int inf=1e9; struct Edge{int from,to,next,v;}e[N<<1]; int head[N],cnt; void ins(int u,int v,int w){ e[++cnt]=(Edge){u,v,head[u],w};head[u]=cnt; } struct Node{ int l,r,mi; }tr[N<<2]; #define lc o<<1 #define rc o<<1|1 void pushup(int o){ tr[o].mi=min(tr[lc].mi,tr[rc].mi); } void build(int o,int l,int r){ tr[o].l=l;tr[o].r=r;tr[o].mi=inf; if(l==r)return ; int mid=l+r>>1; build(lc,l,mid);build(rc,mid+1,r); } void update(int o,int p,int v){ int l=tr[o].l,r=tr[o].r; if(l==r)tr[o].mi=min(tr[o].mi,v); else{ int mid=l+r>>1; if(p<=mid)update(lc,p,v); else update(rc,p,v); pushup(o); } } void modify(int o,int p){ int l=tr[o].l,r=tr[o].r; if(l==r)tr[o].mi=inf; else{ int mid=l+r>>1; if(p<=mid)modify(lc,p); else modify(rc,p); pushup(o); } } int query(int o,int mi){ int l=tr[o].l,r=tr[o].r; if(l==r)return l; else if(mi==tr[lc].mi)return query(lc,mi); else return query(rc,mi); } int query(){ return tr[1].mi; } int dis[N],all; bool inq[N]; void spfa(int s){ memset(dis,0x3f,sizeof(dis)); queue<int>q;q.push(s);dis[s]=0; while(!q.empty()){ int u=q.front();q.pop();inq[u]=0; for(int i=head[u];i;i=e[i].next){ int v=e[i].to; if(dis[v]>dis[u]+e[i].v){ dis[v]=dis[u]+e[i].v; if(!inq[v]){ inq[v]=true; q.push(v); } } } } } bool del[N<<1],onpath[N]; int d[N],pos[N]; void find(int s,int lim){ d[s]=dis[s];queue<int>q;q.push(s); while(!q.empty()){ int u=q.front();q.pop();inq[u]=0; for(int i=head[u];i;i=e[i].next){ if(del[i])continue; int v=e[i].to; if(pos[v]>=lim)update(1,pos[v],d[u]+e[i].v+all-dis[v]); else if(d[v]>d[u]+e[i].v){ d[v]=d[u]+e[i].v; if(!inq[v]){ inq[v]=true; q.push(v); } } } } } int L[N<<1]; int main(){ //freopen("a.in","r",stdin); int n,m,l;scanf("%d%d%d",&n,&m,&l); for(int i=1;i<=m;i++){ int u,v,w;scanf("%d%d%d",&u,&v,&w); ins(u,v,w); } for(int i=1;i<=l;i++){ scanf("%d",&L[i]); onpath[e[L[i]].from]=true; onpath[e[L[i]].to]=true; pos[e[L[i]].to]=i; } build(1,1,l); spfa(1); memset(d,0x3f,sizeof(d));d[1]=0; all=dis[n]; for(int i=1;i<=l;i++){ del[L[i]]=true; find(e[L[i]].from,i); if(query()>=inf)puts("-1"); else printf("%d\n",query()); del[L[i]]=false; modify(1,i); } return 0; }</span>