无向图,给定S和T,多次询问在删除某条边时两点间最短路
我的SPFA被卡了=.=。我们对所有不在最短路径的上的边 ,设它的起点为u 终点为v。那么对于这条边,包含该边的最优的S到T路径就应该是 S-S1-u-v-T1-T 其中S1,T1表示最短路径上的两个点。那么这样的一条最短路可以再S1-T1中某条边被删除时使用,我们用线段树维护这一过程 QWQ 数组开多了有点晕啊
#include<iostream>
#include<algorithm>
#include<cstdlib>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<queue>
using namespace std;
const int maxn=400000+10;
typedef long long LL;
struct tree{int l,r;LL s,lazy;}t[maxn<<2];
struct node{int to,next;LL len;int fr;bool o;}table[maxn<<1];
int tot=1,head[maxn];
void add(int a,int b,int c){table[++tot]=(node){b,head[a],c,a};head[a]=tot;}
int n,m,S,T,Q;
char s[1<<25];
inline long long read()
{
static char *c=s;
if(c==s) fread(c,1,1<<25,stdin);
long long u=0;
while(*c<48) ++c;
while(*c>32) u=u*10+*c++-48;
return u;
}
int pre[maxn],pos[maxn],cnt;
LL f[maxn][2];
bool v[maxn],use[maxn],iskeypoint[maxn];
typedef pair<LL,int>Pair;
void spfa()
{
for(int i=1;i<=n;i++) f[i][0]=1e14;
f[S][0]=0;
priority_queue<Pair,vector<Pair>,greater<Pair> >Q;
Q.push(make_pair(0,S));
while(!Q.empty())
{
Pair top=Q.top();
Q.pop();
int x=top.second;
if(v[x]) continue;
for(int i=head[x];i;i=table[i].next)
if(f[table[i].to][0]>f[x][0]+table[i].len&&!v[table[i].to])
{
pre[table[i].to]=i;
f[table[i].to][0]=f[x][0]+table[i].len;
Q.push(make_pair(f[table[i].to][0],table[i].to));
}
}
}
int ans[maxn][2],num[maxn];
void QWQ(int k)
{
memset(v,0,sizeof v);
for(int i=1;i<=n;i++) f[i][k]=1e14;
priority_queue<Pair,vector<Pair>,greater<Pair> >Q;
if(k==0) f[S][0]=0,Q.push(make_pair(0,S));
else f[T][1]=0,Q.push(make_pair(0,T));
while(!Q.empty())
{
Pair top=Q.top();
Q.pop();
int x=top.second;
if(v[x]) continue;
for(int i=head[x];i;i=table[i].next)
if(f[table[i].to][k]>f[x][k]+table[i].len&&!v[table[i].to])
{
if(iskeypoint[table[i].to]&&iskeypoint[x]) ans[table[i].to][k]=i;
else ans[table[i].to][k]=ans[x][k];
f[table[i].to][k]=f[x][k]+table[i].len;
Q.push(make_pair(f[table[i].to][k],table[i].to));
}
}
}
void maketree(int x,int l,int r)
{
t[x].l=l; t[x].r=r;
t[x].lazy=t[x].s=1e14;
if(l==r) return ;
int mid=l+r>>1;
maketree(x<<1,l,mid);
maketree(x<<1|1,mid+1,r);
t[x].s=min(t[x<<1].s,t[x<<1|1].s);
}
void change(int x,int l,int r,LL tar)
{
if(t[x].l==l&&t[x].r==r)
{
t[x].lazy=min(t[x].lazy,tar);
return ;
}
int mid=t[x].l+t[x].r>>1;
int lc=x<<1,rc=x<<1|1;
if(r<=mid) change(x<<1,l,r,tar);
else if(l>mid) change(x<<1|1,l,r,tar);
else change(x<<1,l,mid,tar),change(x<<1|1,mid+1,r,tar);
}
LL res;
void search(int x,int pos)
{
res=min(res,t[x].lazy);
if(t[x].l==t[x].r) return ;
int mid=t[x].l+t[x].r>>1;
int lc=x<<1,rc=x<<1|1;
if(pos<=mid) return search(x<<1,pos);
return search(x<<1|1,pos);
}
int main()
{
scanf("%d%d",&n,&m);
int x,y,c;
for(int i=1;i<=m;i++)
{
x=read(); y=read(); c=read();
add(x,y,c); add(y,x,c);
}
S=read(); T=read();
spfa();
int hh=T;
while(hh)
{
if(pre[hh]) pos[++cnt]=pre[hh];
use[pre[hh]]=1;
iskeypoint[hh]=1;
table[pre[hh]].o=1;
hh=table[pre[hh]].fr;
}
for(int i=1;i<=cnt;i++) num[i]=pos[i];
for(int i=1;i<=cnt;i++) pos[i]=num[cnt-i+1];
memset(num,0,sizeof num);
for(int i=1;i<=cnt;i++) num[pos[i]]=i;
for(int i=1;i<=n;i++) ans[i][0]=-1,ans[i][1]=tot+1;
QWQ(0); QWQ(1);
maketree(1,1,cnt);
for(int i=1;i<=tot;i++)
if(!use[i])
{
int l=ans[table[i].fr][0],r=ans[table[i].to][1];
int pos1,pos2;
if(l==-1) pos1=1; else pos1=num[l]+1;
if(r==tot+1) pos2=cnt; else pos2=num[r^1]-1;
if(pos1<=pos2) change(1,pos1,pos2,table[i].len+f[table[i].fr][0]+f[table[i].to][1]);
}
Q=read();
while(Q--)
{
x=read(); y=read();
int pos;
if((table[pre[x]].fr==y||table[pre[y]].fr==x)&&iskeypoint[x]&&iskeypoint[y])
{
if(table[pre[y]].fr==x) pos=num[pre[y]];
else pos=num[pre[x]];
res=1e14;
search(1,pos);
if(res>=1e14) puts("Infinity");
else printf("%lld\n",res);
}
else printf("%lld\n",f[T][0]);
}
return 0;
}