zoukankan      html  css  js  c++  java
  • BZOJ2725 : [Violet 6]故乡的梦

    如果S==T,那么答案为0。

    如果S与T不连通,那么答案为inf。

    否则,S到T的最短路径上至少有一条边。

    求出以S为源点的最短路图,是个DAG,随便抓一条S到T的最短路,记为P。

    设dpS[x]表示在这个图上,能到达x点的离S最近的在P上的点,可以通过拓扑排序+DP求出。

    然后求出以T为源点的最短路图,在T的最短路图里找到P。

    设dpT[x]表示在这个图上,能到达x点的离T最近的在P上的点,同样可以通过拓扑排序+DP求出。

    然后把P路径上的边按S到T的方向,从1开始标号。

    对于一条边,如果不在P上,那么答案显然为S到T的最短路。

    否则,对于一条不在P上的边长为w的有向边x->y,P中dpS[x]到dpT[y]-1之间的边删掉后,均可以用disS[x]+disT[y]+w代替。

    用线段树维护即可,时间复杂度$O((n+m)log n+q)$。

    #include<cstdio>
    #include<algorithm>
    #include<queue>
    using namespace std;
    typedef long long ll;
    typedef pair<ll,int> P;
    const int N=200010;
    const ll inf=1LL<<60;
    int n,m,que,S,T,i,x,y,g[N],v[N<<1],w[N<<1],nxt[N<<1],ed;
    int G[N],V[N],NXT[N],pre[N],d[N];
    int path[N],cnt,id[N],fs[N],ft[N];
    int q[N],h,t;
    ll ds[N],dt[N];
    struct E{int x,y,z;}e[N];
    priority_queue<P,vector<P>,greater<P> >Q;
    inline void read(int&a){char c;while(!(((c=getchar())>='0')&&(c<='9')));a=c-'0';while(((c=getchar())>='0')&&(c<='9'))(a*=10)+=c-'0';}
    inline void add(int x,int y,int z){v[++ed]=y;w[ed]=z;nxt[ed]=g[x];g[x]=ed;}
    inline void ADD(int x,int y){pre[y]=x;d[y]++;V[++ed]=y;NXT[ed]=G[x];G[x]=ed;}
    inline int onpath(int x,int y){
      if(!id[x]||!id[y])return 0;
      if(id[x]+1==id[y])return id[x];
      if(id[y]+1==id[x])return id[y];
      return 0;
    }
    ll val[525000],ans[N];
    void build(int x,int a,int b){
      val[x]=inf;
      if(a==b)return;
      int mid=(a+b)>>1;
      build(x<<1,a,mid),build(x<<1|1,mid+1,b);
    }
    void change(int x,int a,int b,int c,int d,ll p){
      if(c<=a&&b<=d){val[x]=min(val[x],p);return;}
      int mid=(a+b)>>1;
      if(c<=mid)change(x<<1,a,mid,c,d,p);
      if(d>mid)change(x<<1|1,mid+1,b,c,d,p);
    }
    void dfs(int x,int a,int b){
      if(a==b){ans[a]=val[x];return;}
      int mid=(a+b)>>1;
      val[x<<1]=min(val[x<<1],val[x]),dfs(x<<1,a,mid);
      val[x<<1|1]=min(val[x<<1|1],val[x]),dfs(x<<1|1,mid+1,b);
    }
    int main(){
      read(n),read(m);
      for(i=1;i<=m;i++){
        read(e[i].x),read(e[i].y),read(e[i].z);
        add(e[i].x,e[i].y,e[i].z);
        add(e[i].y,e[i].x,e[i].z);
      }
      read(S),read(T);
      if(S==T){
        for(read(que);que--;puts("0"));
        return 0;
      }
      for(i=1;i<=n;i++)ds[i]=inf;Q.push(P(ds[S]=0,S));
      while(!Q.empty()){
        P t=Q.top();Q.pop();
        if(ds[t.second]<t.first)continue;
        for(i=g[x=t.second];i;i=nxt[i])if(ds[x]+w[i]<ds[v[i]])Q.push(P(ds[v[i]]=ds[x]+w[i],v[i]));
      }
      if(ds[T]==inf){
        for(read(que);que--;puts("Infinity"));
        return 0;
      }
      for(ed=0,i=1;i<=m;i++){
        if(ds[e[i].x]+e[i].z==ds[e[i].y])ADD(e[i].x,e[i].y);
        if(ds[e[i].y]+e[i].z==ds[e[i].x])ADD(e[i].y,e[i].x);
      }
      for(i=T;i!=S;i=pre[i])path[++cnt]=i;path[++cnt]=S;
      for(i=1;i<cnt-i+1;i++)swap(path[i],path[cnt-i+1]);
      for(i=1;i<=cnt;i++)id[path[i]]=i;
      for(i=1;i<=n;i++)fs[i]=N;
      for(i=1;i<=cnt;i++)fs[path[i]]=i;
      q[h=t=1]=S;
      while(h<=t)for(i=G[x=q[h++]];i;i=NXT[i]){
        if(!id[V[i]])fs[V[i]]=min(fs[V[i]],fs[x]);
        if(!(--d[V[i]]))q[++t]=V[i];
      }
      for(i=1;i<=n;i++)dt[i]=inf;Q.push(P(dt[T]=0,T));
      while(!Q.empty()){
        P t=Q.top();Q.pop();
        if(dt[t.second]<t.first)continue;
        for(i=g[x=t.second];i;i=nxt[i])if(dt[x]+w[i]<dt[v[i]])Q.push(P(dt[v[i]]=dt[x]+w[i],v[i]));
      }
      for(ed=0,i=1;i<=n;i++)G[i]=d[i]=0;
      for(i=1;i<=m;i++){
        if(dt[e[i].x]+e[i].z==dt[e[i].y])ADD(e[i].x,e[i].y);
        if(dt[e[i].y]+e[i].z==dt[e[i].x])ADD(e[i].y,e[i].x);
      }
      for(i=1;i<=cnt;i++)ft[path[i]]=i;
      q[h=t=1]=T;
      while(h<=t)for(i=G[x=q[h++]];i;i=NXT[i]){
        if(!id[V[i]])ft[V[i]]=max(ft[V[i]],ft[x]);
        if(!(--d[V[i]]))q[++t]=V[i];
      }
      build(1,1,cnt-1);
      for(i=1;i<=m;i++){
        x=e[i].x,y=e[i].y;
        if(onpath(x,y))continue;
        if(fs[x]<N&&ft[y]&&fs[x]<ft[y])change(1,1,cnt-1,fs[x],ft[y]-1,ds[x]+dt[y]+e[i].z);
        if(fs[y]<N&&ft[x]&&fs[y]<ft[x])change(1,1,cnt-1,fs[y],ft[x]-1,ds[y]+dt[x]+e[i].z);
      }
      dfs(1,1,cnt-1);
      read(que);
      while(que--){
        read(x),read(y),i=onpath(x,y);
        if(!i){printf("%lld
    ",ds[T]);continue;}
        if(ans[i]<inf)printf("%lld
    ",ans[i]);else puts("Infinity");
      }
      return 0;
    }
    

      

  • 相关阅读:
    Generative Adversarial Nets
    【 剑指Offer 1 】数据结构
    Hopfield神经网络
    LSTMs 长短期记忆网络系列
    【 记忆网络 2 】 End-to-End Memory Network
    MessagePack Java Jackson Dataformat
    MessagePack Java 0.6.X 动态类型
    MessagePack Java 0.6.X 可选字段
    MessagePack Java 0.6.X 不使用注解(annotations)来序列化
    MessagePack Java 0.6.X List, Map 对象的序列化和反序列化
  • 原文地址:https://www.cnblogs.com/clrs97/p/4859897.html
Copyright © 2011-2022 走看看