bzoj 2725 [Violet 6]故乡的梦

来源:互联网 发布:java手机网游有哪些 编辑:程序博客网 时间:2024/05/01 03:43

无向图,给定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;}



1 0