最小割树学习

代码

#include<bits/stdc++.h>
using namespace std;
#define fi first
#define se second
#define mp make_pair
#define pb push_back
const int inf = 0x3f3f3f3f;
int pr[200100][23],g[200100][23],vis[200100],n,m,Q,wh[200100],now[200100];
int head[200100],to[200100],nxt[200100],w[200100],ano[200100],cnt,tim;
int level[200100],cur[200100],dep[200100],old[200100];
vector<pair<int,int> >v[200100];
struct GHT {
    inline void add(int x,int y,int z){
      nxt[++cnt]=head[x];
      head[x]=cnt;
      to[cnt]=y;
      w[cnt]=z;
      old[cnt]=z;
      nxt[++cnt]=head[y];
      head[y]=cnt;
      to[cnt]=x;
      w[cnt]=z;
      old[cnt]=z;
      ano[cnt]=cnt-1;
      ano[cnt-1]=cnt;
    }
    inline int bfs(int s,int t){
      memset(level,-1,sizeof(level));
      queue<int>q;
      q.push(s);
      level[s]=0;
      while(!q.empty()){
          int x=q.front();
          q.pop();
          for(int i=head[x];i;i=nxt[i])
            if(level[to[i]]==-1&&w[i]){
                level[to[i]]=level[x]+1;
                if(to[i]==t)return 1;
                q.push(to[i]);
          }
      }
      return 0;
    }
    inline int dfs(int x,int t,int flow){
      if(x==t||!flow)return flow;
      int res=0;
      cur[x]=head[x];
      for(int i=cur[x];i;i=nxt[i]){
          cur[x]=i;
          if(level[to[i]]==level[x]+1&&w[i]){
            int f=dfs(to[i],t,min(flow-res,w[i]));
            w[i]-=f;
            w[ano[i]]+=f;
            res+=f;
        }
      }
      if(!res)level[x]=-1;
      return res;
    }
    inline void dfs1(int x){
      vis[x]=tim;
      for(int i=head[x];i;i=nxt[i])
        if(w[i]&&vis[to[i]]!=tim)dfs1(to[i]);
    }
    inline void build(int le,int ri){
      int i,j,k;
      if(le>=ri)return;
      int x=wh[le],y=wh[le+1],z=0;
      for(i=1;i<=cnt;i++)w[i]=old[i];
      while(bfs(x,y))while(int a=dfs(x,y,inf))z+=a;
      tim++;dfs1(x);
      int p=le,q=ri;
      for(i=le;i<=ri;i++)
        if(vis[wh[i]]==tim)now[p++]=wh[i];
          else now[q--]=wh[i];
      for(i=le;i<=ri;i++)wh[i]=now[i];
      v[x].pb(mp(y,z));
      v[y].pb(mp(x,z));
      build(le,p-1),build(q+1,ri);
    }
    inline void sol(int x,int fa){
      dep[x]=dep[fa]+1;
      for(int i=0;i<v[x].size();i++){
          int y=v[x][i].fi,z=v[x][i].se;
          if(y==fa)continue;
          pr[y][0]=x;
          g[y][0]=z;
          sol(y,x);
      }
    }
    inline void deal(){
      int i,j,k;
      for(i=1;i<=20;i++)
        for(j=1;j<=n;j++){
          pr[j][i]=pr[pr[j][i-1]][i-1];
          g[j][i]=min(g[j][i-1],g[pr[j][i-1]][i-1]);
        }
    }
    inline int que(int x,int y){
      if(dep[x]<dep[y])swap(x,y);
      int i,j,k,len=dep[x]-dep[y],ans=inf;
      for(i=0;i<=20;i++)
        if((1<<i)&len){
          ans=min(ans,g[x][i]);
          x=pr[x][i];
        }
      if(x==y)return ans;
      for(i=20;i>=0;i--)
        if(pr[x][i]!=pr[y][i]){
          ans=min(ans,min(g[x][i],g[y][i]));
          x=pr[x][i],y=pr[y][i];
        }
      return min(ans,min(g[x][0],g[y][0]));
    }
};
GHT T;
int main(){
    int i,j,k;
    scanf("%d%d",&n,&m);
    for(i=1;i<=m;i++){
      int x,y,z;
      scanf("%d%d%d",&x,&y,&z);
      T.add(x,y,z);
    }
    memset(g,0x3f,sizeof(g));
    for(i=1;i<=n;i++)wh[i]=i;
    T.build(1,n);
    T.sol(1,0);
    T.deal();
    scanf("%d",&Q);
    while(Q--){
      int x,y;
      scanf("%d%d",&x,&y);
      printf("%d\n",T.que(x,y));
    }
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/yzxverygood/p/11547178.html