传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=2725
http://www.lydsy.com/JudgeOnline/problem.php?id=4400
思路:首先随便找到一条最短路
如果删除一条边(x,y),那么最短路就会绕开x和y走一段
即S->最短路上的一个点->不在最短路的某些边->最短路上的一个点->T
对于每个不在选定的最短路上的点,求出fs[x]表示S到x的最短路在哪个点脱离选定的最短路
ft[y]表示从y到T的最短路在哪个点进入选定的最短路
即S->fs[x]->x->y->ft[y]->T
那么对于一条不在最短路的边,它就有可能在删去fs[x]与ft[y]之间的最短路边时发挥作用
记录ans[i]表示最短路上第i条边删去后的答案
处理每条不在最短路上的边,就在线段树上对fs[x]到ft[y]这段区间覆盖取min即可。
4400类似,因为找fs和ft时没有判是否已经找过,直接被卡T,上pbds都没用.
#include<queue> #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #define ls (p<<1) #define rs ((p<<1)|1) #define mid ((l+r)>>1) #define mp(a,b) make_pair(a,b) #define dist first #define id second #define abs(a) (a>0?a:-(a)) typedef long long ll; const int maxn=200010,maxm=400010; using namespace std; typedef pair<ll,int> PI; int pre[maxm],now[maxn],son[maxm],tot,n,m,Q,S,T,pos[maxn],len,idx[maxn],fs[maxn],ft[maxn]; ll ds[maxn],dt[maxn],inf,ans[maxn],val[maxm]; struct Edge{int u,v;ll w;}E[maxm]; struct Tsegment{ ll cov[maxn<<2],v[maxn<<2]; void cover(int p,ll va){v[p]=min(v[p],va),cov[p]=min(cov[p],va);} void down(int p){if (cov[p]!=inf) cover(ls,cov[p]),cover(rs,cov[p]),cov[p]=inf;} void build(int p,int l,int r){ cov[p]=v[p]=inf;if (l==r) return; build(ls,l,mid),build(rs,mid+1,r); } void modify(int p,int l,int r,int a,int b,ll va){ if (l==a&&r==b){cover(p,va);return;} down(p); if (b<=mid) modify(ls,l,mid,a,b,va); else if (a>mid) modify(rs,mid+1,r,a,b,va); else modify(ls,l,mid,a,mid,va),modify(rs,mid+1,r,mid+1,b,va); } void query(int p,int l,int r){ if (l==r){ans[l]=v[p];return;} down(p),query(ls,l,mid),query(rs,mid+1,r); } void modify(int l,int r,ll va){modify(1,1,len-1,l,r,va);} void query(){query(1,1,len-1);} }Tree; priority_queue<PI,vector<PI>,greater<PI> > q; int que[maxm+10],head,tail;bool vis[maxn]; bool inpath(int x,int y){return pos[x]&&pos[y]&&abs(pos[x]-pos[y])==1;} void add(int a,int b,ll c){pre[++tot]=now[a],now[a]=tot,son[tot]=b,val[tot]=c;} void dijkstra(int s,ll dis[]){ q.push(mp(dis[s]=0,s)),inf=dis[0]; while (!q.empty()){ PI x=q.top();q.pop(); for (int y=now[x.id];y;y=pre[y]) if (x.dist+val[y]<dis[son[y]]) q.push(mp(dis[son[y]]=x.dist+val[y],son[y])); } } void getway(){ for (int x=S,last=-1;;){ pos[x]=++len,idx[len]=x; if (x==T) break; for (int y=now[x];y;y=pre[y]) if (son[y]!=last&&ds[x]+val[y]+dt[son[y]]==ds[T]){last=x,x=son[y];break;} } } void getfir(int s,ll dis[],int fir[]){ que[tail=1]=s,fir[s]=s,head=0; while (head!=tail){ int x=que[++head>maxm?1:head]; for (int y=now[x];y;y=pre[y]) if (!pos[son[y]]&&!fir[son[y]]&&dis[son[y]]==dis[x]+val[y])//要判!fir[son[y]] que[++tail>maxm?1:tail]=son[y],fir[son[y]]=s; } } int main(){ scanf("%d%d",&n,&m);ll z; for (int i=1,x,y;i<=m;i++) scanf("%d%d%lld",&x,&y,&z),E[i]=(Edge){x,y,z},add(x,y,z),add(y,x,z); scanf("%d%d%d",&S,&T,&Q); memset(ds,63,sizeof(ds)),dijkstra(S,ds); if (ds[T]==inf){ for (int i=1;i<=Q;i++) puts("Infinity"); return 0; } memset(dt,63,sizeof(dt)),dijkstra(T,dt),getway(); for (int i=1;i<=len;i++) getfir(idx[i],ds,fs); for (int i=len;i;i--) getfir(idx[i],dt,ft); Tree.build(1,1,len-1); for (int i=1;i<=m;i++){ int u=E[i].u,v=E[i].v;ll w=E[i].w; if (!fs[u]||!fs[v]||inpath(u,v)) continue; if (pos[fs[u]]<pos[ft[v]]) Tree.modify(pos[fs[u]],pos[ft[v]]-1,ds[u]+dt[v]+w); if (pos[fs[v]]<pos[ft[u]]) Tree.modify(pos[fs[v]],pos[ft[u]]-1,ds[v]+dt[u]+w); } Tree.query(); for (int i=1,x,y;i<=Q;i++){ scanf("%d%d",&x,&y); if (!inpath(x,y)) printf("%lld ",ds[T]); else{ if (pos[x]>pos[y]) swap(x,y); if (ans[pos[x]]>=inf) puts("Infinity"); else printf("%lld ",ans[pos[x]]); } } return 0; }
#include<ctime> #include<queue> #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #include<ext/pb_ds/priority_queue.hpp> #define max(a,b) (a>b?a:b) #define min(a,b) (a<b?a:b) #define swap(a,b) std::swap(a,b) #define ls (p<<1) #define rs ((p<<1)|1) #define mid ((l+r)>>1) #define mp(a,b) std::make_pair(a,b) #define dist first #define id second #define abs(a) (a>0?a:-(a)) //typedef long long int; const int maxn=200010,maxm=400010; //using namespace std; typedef std::pair<int,int> PI; int pre[maxm],now[maxn],son[maxm],tot=1,n,m,Q,S,T,pos[maxn],len,idx[maxn],fs[maxn],ft[maxn],cnt; int ds[maxn],dt[maxn],inf,ans[maxn],val[maxm],res,ord[maxm]; struct Edge{int u,v;int w;}E[maxm]; struct Tsegment{ int cov[maxn<<2],v[maxn<<2]; void cover(int p,int va){v[p]=min(v[p],va),cov[p]=min(cov[p],va);} void down(int p){if (cov[p]!=inf) cover(ls,cov[p]),cover(rs,cov[p]),cov[p]=inf;} void build(int p,int l,int r){ cov[p]=v[p]=inf;if (l==r) return; build(ls,l,mid),build(rs,mid+1,r); } void modify(int p,int l,int r,int a,int b,int va){ if (l==a&&r==b){cover(p,va);return;} down(p); if (b<=mid) modify(ls,l,mid,a,b,va); else if (a>mid) modify(rs,mid+1,r,a,b,va); else modify(ls,l,mid,a,mid,va),modify(rs,mid+1,r,mid+1,b,va); } void query(int p,int l,int r){ if (l==r){ans[l]=v[p];return;} down(p),query(ls,l,mid),query(rs,mid+1,r); } void modify(int l,int r,int va){modify(1,1,len-1,l,r,va);} void query(){query(1,1,len-1);} }Tree; using namespace __gnu_pbds; priority_queue<PI,std::greater<PI>,pairing_heap_tag> q; int que[maxm+10],head,tail;bool vis[maxn],inpath[maxm]; void add(int a,int b,int c){pre[++tot]=now[a],now[a]=tot,son[tot]=b,val[tot]=c;} void dijkstra(int s,int dis[]){ q.push(mp(dis[s]=0,s)),inf=dis[0]; static bool upd[maxn]; memset(upd+1,0,sizeof(bool)*n); while (!q.empty()){ PI x=q.top();q.pop(); if (upd[x.id]) continue;upd[x.id]=1; for (int y=now[x.id];y;y=pre[y]) if (x.dist+val[y]<dis[son[y]]) q.push(mp(dis[son[y]]=x.dist+val[y],son[y])); } } void getway(){ for (int x=S,last=-1;;){ pos[x]=++len,idx[len]=x; if (x==T) break; for (int y=now[x];y;y=pre[y]) if (son[y]!=last&&ds[x]+val[y]+dt[son[y]]==ds[T]){last=x,x=son[y],inpath[y>>1]=1;break;} } } void getfir(int s,int dis[],int fir[]){ que[tail=1]=s,fir[s]=s,head=0; while (head!=tail){ int x=que[++head>maxm?1:head]; for (int y=now[x];y;y=pre[y]) if (!pos[son[y]]&&!fir[son[y]]&&dis[son[y]]==dis[x]+val[y]) que[++tail>maxm?1:tail]=son[y],fir[son[y]]=s; } } int main(){ //freopen("boss8.in","r",stdin); scanf("%d%d",&n,&m);int z;// for (int i=1,x,y;i<=m;i++){ scanf("%d%d%d",&x,&y,&z); if (x>y) swap(x,y); E[i]=(Edge){x,y,z}; add(x,y,z),add(y,x,z); } S=1,T=n; memset(ds,63,sizeof(int)*(n+1)),dijkstra(S,ds); memset(dt,63,sizeof(int)*(n+1)),dijkstra(T,dt); getway();//int t1=(int)clock(); for (int i=1;i<=len;i++) getfir(idx[i],ds,fs); for (int i=len;i;i--) getfir(idx[i],dt,ft); //int t2=(int)clock();printf("step1 %d ",t2-t1); Tree.build(1,1,len-1); for (int i=1;i<=m;i++){ int u=E[i].u,v=E[i].v;int w=E[i].w; if (!fs[u]||!fs[v]||inpath[i]) continue; if (pos[fs[u]]<pos[ft[v]]) Tree.modify(pos[fs[u]],pos[ft[v]]-1,ds[u]+dt[v]+w); if (pos[fs[v]]<pos[ft[u]]) Tree.modify(pos[fs[v]],pos[ft[u]]-1,ds[v]+dt[u]+w); } Tree.query(); //for (int i=1;i<len;i++) printf("%d ",ans[i]); for (int i=1;i<len;i++) res=max(res,ans[i]); for (int i=1;i<len;i++) cnt+=(ans[i]==res); printf("%d %d ",res,res==ds[T]?m:cnt);// return 0; }