[删边最短路 并查集||线段树] BZOJ 2725 [Violet 6]故乡的梦 & 4400 tjoi2012 桥
2016-11-04 07:04
549 查看
首先求出一条S到T的最短路P,如果不是最短路上的边删了肯定不影响答案。
接着证明去掉一条边(u,v)之后最短路一定是这样存在一条边(x,y),然后最短路径是S->x->y->T,并且S->x,y->T都是原图中的最短路。
考虑S的最短路径图和T的最短路径图。
于是只要考虑一条边(x,y),然后求出S到x的最短路和这条最短路最早什么时候离开P,记作x’,同理求出y’。
于是(x,y)这条边可以更新x’到y’之间的答案。
接着证明去掉一条边(u,v)之后最短路一定是这样存在一条边(x,y),然后最短路径是S->x->y->T,并且S->x,y->T都是原图中的最短路。
考虑S的最短路径图和T的最短路径图。
于是只要考虑一条边(x,y),然后求出S到x的最短路和这条最短路最早什么时候离开P,记作x’,同理求出y’。
于是(x,y)这条边可以更新x’到y’之间的答案。
#include<cstdio> #include<cstdlib> #include<algorithm> #include<map> #include<queue> #include<cstring> #define U G[p].u #define V G[p].v #define W G[p].w #define cl(x) memset(x,0,sizeof(x)) using namespace std; typedef long long ll; typedef pair<ll,int> abcd; inline char nc(){ static char buf[100000],*p1=buf,*p2=buf; if (p1==p2) { p2=(p1=buf)+fread(buf,1,100000,stdin); if (p1==p2) return EOF; } return *p1++; } inline void read(int &x){ char c=nc(),b=1; for (;!(c>='0' && c<='9');c=nc()) if (c=='-') b=-1; for (x=0;c>='0' && c<='9';x=x*10+c-'0',c=nc()); x*=b; } const int M=200005; const int N=200005; /*struct Queue{ priority_queue<abcd,vector<abcd>,greater<abcd> > Q,del; void maintain(){ while (!Q.empty()&&!del.empty()&&Q.top()==del.top()) Q.pop(),del.pop(); } void push(abcd x){ maintain(); Q.push(x); } void pop(){ maintain(); if (!Q.empty()) Q.pop(); } void erase(abcd x){ maintain(); del.push(x); } abcd top(){ maintain(); return Q.top(); } bool empty(){ maintain(); return Q.empty(); } void clear() { while (!Q.empty()) Q.pop(); while (!del.empty()) del.pop(); } }Q;*/ struct edge{ int u,v,w,next; }G[M<<1]; int head ,inum=1; int fla[M<<1]; inline void add(int u,int v,int w,int p){ G[p].u=u; G[p].v=v; G[p].w=w; G[p].next=head[u]; head[u]=p; } namespace DIJ{ #define val(x) dis[H[x]] #define K(x) (x<<1|1)>cnt?(x<<1):(val(x<<1)<val(x<<1|1)?(x<<1):(x<<1|1)) ll* dis; int H ; int cnt,back ,vst ; inline void Swp(int x,int y){ swap(H[x],H[y]); swap(back[H[x]],back[H[y]]); } inline void Up(int x){ for (;x && val(x)<val(x>>1);x>>=1) Swp(x,x>>1); } inline void Down(int x){ for (int tmp;(x<<1)<=cnt && val(x)>val(tmp=K(x));x=tmp) Swp(x,tmp); } inline void Dij(int S,int n,ll *dis){ int u; DIJ::dis=dis; cnt=0; H[++cnt]=S; back[S]=cnt; dis[S]=0; vst[S]=1; for (int i=1;i<=n;i++) if (i!=S) H[++cnt]=i,back[i]=cnt,dis[i]=1LL<<60,vst[i]=0; for (int i=1;i<n;i++){ u=H[1]; vst[H[1]]=1; Swp(1,cnt--); Down(1); for (int p=head[u];p;p=G[p].next) if (!vst[V] && dis[V]>dis[U]+G[p].w){ dis[V]=dis[U]+G[p].w; Up(back[V]); } } } } int n,m; ll disS ,disT ; /*inline void Dij(int S,ll *dis){ Q.clear(); for (int i=1;i<=n;i++) dis[i]=1LL<<60; dis[S]=0; Q.push(abcd(0,S)); for (int i=1;i<=n;i++){ abcd t=Q.top(); Q.pop(); int u=t.second; for (int p=head[u];p;p=G[p].next) if (dis[V]>dis[u]+G[p].w){ Q.erase(abcd(dis[V],V)); dis[V]=dis[u]+G[p].w; Q.push(abcd(dis[V],V)); } } }*/ int S,T; int path ,tot,inpath ; map<abcd,int> Map; int fx ,fy ; int lst ,pnt; int vst ; inline void dfs(int u,ll *dis){ vst[u]=1; for (int p=head[u];p;p=G[p].next) if (!vst[V] && dis[V]==dis[u]+G[p].w) dfs(V,dis); lst[++pnt]=u; } int fat ; inline void init(int n){ for (int i=1;i<=n;i++) fat[i]=i; } inline int Fat(int u){ return u==fat[u]?u:fat[u]=Fat(fat[u]); } struct data{ int l,r; ll w; data(int l=0,int r=0,ll w=0):l(l),r(r),w(w) { } bool operator < (const data &B) const{ return w<B.w; } }edges[M<<1]; int Tot; ll ans[M]; int Que ,l,r; inline void getfir(int s,ll* dis,int* fir){ l=r=-1; Que[++r]=s; fir[s]=inpath[s]; while (l<r){ int u=Que[++l]; for (int p=head[u];p;p=G[p].next) if (!inpath[V] && !fir[V] && dis[V]==dis[u]+G[p].w) Que[++r]=V,fir[V]=inpath[s]; } } void getway(){ for (int x=S,last=-1;;){ inpath[x]=++tot,path[tot]=x; if (x==T) break; for (int p=head[x];p;p=G[p].next) if (V!=last&&disS[x]+G[p].w+disT[V]==disS[T]){last=x,x=V;break;} } } int main(){ int iu,iv,iw; freopen("t.in","r",stdin); freopen("t.out","w",stdout); read(n); read(m); for (int i=1;i<=m;i++){ read(iu); read(iv); read(iw); add(iu,iv,iw,++inum); add(iv,iu,iw,++inum); Map[abcd(iu,iv)]=Map[abcd(iv,iu)]=inum>>1; } read(S); read(T); DIJ::Dij(S,n,disS); DIJ::Dij(T,n,disT); // for (int i=T;i;i=pre[i]) path[++tot]=i; reverse(path+1,path+tot+1); // for (int i=1;i<=tot;i++) inpath[path[i]]=i; getway(); for (int i=1;i<tot;i++) fla[Map[abcd(path[i],path[i+1])]]=1; // dfs(S,disS); reverse(lst+1,lst+pnt+1); for (int i=1;i<=tot;i++) getfir(path[i],disS,fx); /*memset(fx,0x7f,sizeof(fx)); for (int i=1;i<=tot;i++) fx[path[i]]=i; for (int i=1;i<=pnt;i++) for (int p=head[lst[i]];p;p=G[p].next) if (!inpath[V] && disS[V]==disS[G[p].u]+G[p].w) fx[V]=min(fx[V],fx[lst[i]]); pnt=0; cl(vst);*/ // dfs(T,disT); reverse(lst+1,lst+pnt+1); for (int i=tot;i;i--) getfir(path[i],disT,fy); /*for (int i=1;i<=tot;i++) fy[path[i]]=i; for (int i=1;i<=pnt;i++) for (int p=head[lst[i]];p;p=G[p].next) if (!inpath[V] && disT[V]==disT[G[p].u]+G[p].w) fy[V]=max(fy[V],fy[lst[i]]);*/ for (int p=2;p<=inum;p++) if (!fla[p>>1]) if (fx[U]<=fy[V]-1) edges[++Tot]=data(fx[U],fy[V]-1,disS[U]+W+disT[V]); sort(edges+1,edges+Tot+1); init(tot); for (int i=1;i<tot;i++) ans[i]=1LL<<60; for (int i=1;i<=Tot;i++) for (int j=Fat(edges[i].l);j<=edges[i].r;j=Fat(j)) ans[j]=edges[i].w,fat[j]=j+1; int Q; ll Ans; read(Q); while (Q--){ read(iu); read(iv); int p=Map[abcd(iu,iv)]; if (!fla[p]) Ans=disS[T]; else{ iu=inpath[iu],iv=inpath[iv]; if (iu>iv) swap(iu,iv); Ans=ans[iu]; } if (Ans==1LL<<60) printf("Infinity\n"); else printf("%lld\n",Ans); } return 0; }
相关文章推荐
- bzoj2725: [Violet 6]故乡的梦&&bzoj4400: tjoi2012 桥
- bzoj2725 [Violet 6] 故乡的梦 && 4400 tjoi2012 桥 Dijkstra+线段树
- BZOJ 2725: [Violet 6]故乡的梦 最短路+线段树
- BZOJ 2725 [Violet 6]故乡的梦 最短路
- BZOJ 4400(tjoi2012 桥-最短路树)
- bzoj4400: tjoi2012 桥
- [原博客] BZOJ 2725 : [Violet 6]故乡的梦
- BZOJ3673 & BZOJ3674 可持续化并查集 【可持续化线段树维护可持续化数组】
- 【BZOJ 3674】可持久化并查集加强版&【BZOJ 3673】可持久化并查集 by zky 用可持久化线段树破之
- bzoj4552 [ TJOI2016 && HEOI2016 ] -- 二分+线段树
- 【BZOJ3673】&&【BZOJ3674】: 可持久化并查集 by zky 可持久化线段树
- 【BZOJ】3673: 可持久化并查集 by zky & 3674: 可持久化并查集加强版(可持久化线段树)
- 【BZOJ-3673&3674】可持久化并查集 可持久化线段树 + 并查集
- BZOJ 2725 [Violet 6]故乡的梦
- bzoj 2725: [Violet 6]故乡的梦 堆优化Dijkstra+线段树
- BZOJ3673 & BZOJ3674 可持续化并查集 【可持续化线段树维护可持续化数组】
- bzoj1230[Usaco2008 Nov]&&[TJOI2009]开关灯(线段树)
- bzoj 2725 [Violet 6]故乡的梦
- bzoj 3673&&3674 可持久化并查集 可持久化线段树
- BZOJ 2733 [HNOI2012]永无乡 ——线段树 并查集