堆优dijkstra+线段树
膜:http://blog.csdn.net/popoqqq/article/details/47841783
为了表达清楚,记不删边时最短路为E1,删去某一条E1上的边之后的最短路为E2
显然E2一定是形如:S->沿着E1走到某一个在E1上点的S’->沿着不属于E1的一些边走到某一在E1上点的T’->沿着E1走到T
而且可以证明,上面提到的E2中不属于E1的那些边(组成一条路径)中,一定存在至少一条边,记它的两端点为u,v,使得E2上沿着S->u的路径是S->u在原图中的最短路,E2上沿着v->T的路径是v->T在原图中的最短路。
这个可以通过反证法证明,前提是原图为无向图。
然而其实这一题我并没有AC。。。不知道是因为复杂度退化了还是常数太大了,一直T。。。
#include<map>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define N 200005
#define cmin(u,v) (u)>(v)?(u)=(v):0
#define mkp(a,b) (1ll*a*N+b)
#define reg register
using namespace std;
int in()
{
register long long r = 0;
register char c = getchar();
while(c<'0'||c>'9')c = getchar();
while(c>='0'&&c<='9')r = r*10+c-'0', c=getchar();
return r;
}
char ss[100];
inline void out(long long x)
{
if(x==0) {putchar(48); return;}
char *s=ss;
while(x) *(++s)=x%10, x/=10;
while(s!=ss) putchar((*(s--))+48);
putchar('\n');
}
map<long long,bool> PathEdge;
map<long long,int> PathId;
struct node
{
int id;
long long dis;
node(){}
node(int a, long long b):id(a),dis(b){}
}heap[N<<1];
struct Segment_tree
{
int l, r;
long long val, lazy;
}t[N*5];
struct edge{int from,next,to, val;}e[N<<1];
const long long INF = 1ll<<61;
long long dis[N], ds[N], dt[N], print[N];
int n, last[N], ecnt=1, fa[N], fs[N], ft[N], ll[N], rl[N], mapp[N], tcnt, ct[N], ctt, tot;
bool vis[N], PathPoint[N];
void addedge(int a, int b, int c)
{
e[++ecnt]=(edge){a,last[a],b,c};
last[a]=ecnt;
PathId[mkp(a,b)]=ecnt;
}
void heap_add(node x)
{
heap[++tot]=x;
for(reg int i=tot,j=i>>1;j;i=j,j>>=1)
{
if(heap[j].dis>heap[i].dis)
swap(heap[j],heap[i]);
else break;
}
}
void heap_pop()
{
heap[1]=heap[tot--];
for(reg int i=1,j=i<<1;j<=tot;i=j,j<<=1)
{
if(j<tot&&heap[j].dis>heap[j|1].dis)j|=1;
if(heap[j].dis<heap[i].dis)
swap(heap[j],heap[i]);
else break;
}
}
void dijk(int s)
{
memset(vis,0,sizeof(vis));
memset(dis,0x7f,sizeof(dis));
heap_add(node(s,dis[s]=0));
while(tot)
{
int x=heap[1].id;
heap_pop();
if(vis[x])continue;
vis[x]=1;
for(reg int i = last[x]; i; i=e[i].next)
{
int y=e[i].to;
if(vis[y] || dis[x]+e[i].val>=dis[y])continue;
dis[y]=dis[x]+e[i].val;
fa[y]=x;
heap_add(node(y,dis[y]));
}
}
}
void dijk2(int s, int *fs, long long *ds)
{
memset(vis,0,sizeof(vis));
memset(ds,0x7f,sizeof(dis));
heap_add(node(s,ds[s]=0));
while(tot)
{
int x=heap[1].id;
heap_pop();
if(vis[x])continue;
vis[x]=1;
if(PathPoint[fa[x]] && (!PathPoint[x]))
fs[x]=fa[x];
else if(PathPoint[x])fs[x]=x;
else fs[x]=fs[fa[x]];
for(reg int i = last[x]; i; i=e[i].next)
{
int y=e[i].to;
if(vis[y] || ds[x]+e[i].val>=ds[y])continue;
ds[y]=ds[x]+e[i].val;
fa[y]=x;
heap_add(node(y,ds[y]));
}
}
}
void pushdown(int x)
{
cmin(t[x<<1].val,t[x].lazy);
cmin(t[x<<1|1].val,t[x].lazy);
cmin(t[x<<1].lazy,t[x].lazy);
cmin(t[x<<1|1].lazy,t[x].lazy);
t[x].lazy=INF;
}
void merge(int x)
{
cmin(t[x].val,t[x<<1].val);
cmin(t[x].val,t[x<<1|1].val);
}
void build(int x, int l, int r)
{
t[x].l=l; t[x].r=r; t[x].val=INF; t[x].lazy=INF;
if(l==r)return;
int mid=(l+r)>>1;
build(x<<1,l,mid);
build(x<<1|1,mid+1,r);
}
void update(int x, int l, int r, long long v)
{
pushdown(x);
if(l<=t[x].l && t[x].r<=r)
{
cmin(t[x].val,v);
cmin(t[x].lazy,v);
return;
}
int mid=(t[x].l+t[x].r)>>1;
if(l<=mid)update(x<<1,l,r,v);
if(mid+1<=r)update(x<<1|1,l,r,v);
merge(x);
}
void ask(int x)
{
pushdown(x);
if(t[x].l==t[x].r)
{
print[t[x].l]=t[x].val;
return;
}
ask(x<<1);
ask(x<<1|1);
}
int main()
{
int m, s, t, Q;
n=in();m=in();
for(reg int i = 1, a, b, c; i <= m; i++)
{
a=in(); b=in(); c=in();
addedge(a,b,c);
addedge(b,a,c);
}
s=in(); t=in(); Q=in();
dijk(s);
PathPoint[s]=1;
for(reg int pos = t; fa[pos]; pos=fa[pos])
{
ct[pos]=++ctt;
PathPoint[pos]=1;
PathEdge[mkp(pos,fa[pos])]=1;
PathEdge[mkp(fa[pos],pos)]=1;
ll[pos]=PathId[mkp(fa[pos],pos)]>>1;
rl[fa[pos]]=PathId[mkp(fa[pos],pos)]>>1;
mapp[ll[pos]]=++tcnt;
}
ct[s]=++ctt;
fa[s]=0;dijk2(s,fs,ds);
fa[t]=0;dijk2(t,ft,dt);
build(1,1,ecnt>>1);
for(reg int i = 2; i <= ecnt; i+=2)
{
int a=e[i].from, b=e[i].to, val=e[i].val;
if(!PathEdge[mkp(a,b)])
{
if(mapp[ll[ft[b]]] && mapp[ll[ft[b]]]<=mapp[rl[fs[a]]])update(1,mapp[ll[ft[b]]],mapp[rl[fs[a]]],ds[a]+dt[b]+val);
if(mapp[ll[ft[a]]] && mapp[ll[ft[a]]]<=mapp[rl[fs[b]]])update(1,mapp[ll[ft[a]]],mapp[rl[fs[b]]],ds[b]+dt[a]+val);
}
}
if(dis[t]>=INF)
{
for(;Q--;)
printf("Infinity\n");
return 0;
}
memset(print,0x7f,sizeof(print));
ask(1);
for(;Q--;)
{
int a=in(), b=in();
if(!PathEdge[mkp(a,b)])printf("%lld\n",dis[t]);
else
{
if(ct[a]<ct[b])swap(a,b);
long long ans = print[mapp[ll[ft[b]]]];
if(ans==INF)printf("Infinity\n");
else printf("%lld\n",ans);
}
}
}