您的位置:首页 > 其它

[删边最短路 并查集||线段树] 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’之间的答案。

#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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: