最小割树(洛谷4897)

最小割树

求任意两点间的最小割

每次把当前点集中任意两点uv作为源汇跑最小割,连一条uv之间权值为最小割的边,之后按照分成的集合向下做

两点间最小割=新图中路径上的最小边权

code

还在调

#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#define fo(a,b,c) for (a=b; a<=c; a++)
#define fd(a,b,c) for (a=b; a>=c; a--)
#define min(a,b) (a<b?a:b)
#define inf 2133333333
using namespace std;

int aa[1111][3];
int Ls[512];
int a[3102][3];
int A[3102];
int ls[512];
int cur[512];
int f[512];
int g[512];
int d[512][512];
int b[512];
int bz[512];
int d2[512];
int fa[512][9];
int mn[512][9];
int D[512];
int Q,n,m,i,j,k,l,len,st,ed,Len,h2,t2,x,y;

void New(int x,int y,int z)
{
    ++len;
    a[len][0]=y;
    a[len][1]=ls[x];
    ls[x]=len;
    a[len][2]=A[len]=z;
}

void NEW(int x,int y,int z)
{
    ++Len;
    aa[Len][0]=y;
    aa[Len][1]=Ls[x];
    Ls[x]=Len;
    aa[Len][2]=z;
}

int dfs(int t,int flow)
{
    int i,use=0;
    
    if (t==ed)
    return flow;
    
    for (i=cur[t]; i; i=a[i][1])
    {
        cur[t]=i;
        
        if (f[t]==f[a[i][0]]+1 && a[i][2])
        {
            int w=dfs(a[i][0],min(flow-use,A[i]));
            
            a[i][2]+=w;
            a[i^1][2]-=w;
            use+=w;
            
            if (use==flow)
            return use;
        }
    }
    cur[t]=ls[t];
    
    --g[f[t]];
    if (!g[f[t]])
    {
        f[st]=n+1;
        return use;
    }
    ++f[t];++g[f[t]];
    
    return use;
}

void work(int t)
{
    int Ans=0;
    
    if (b[t]<=1)
    return;
    
    memset(f,0,sizeof(f));
    memset(g,0,sizeof(g));
    fo(i,1,len) a[i][2]=A[i];
    
    g[0]=n;
    st=d[t][1];
    ed=d[t][2];
    
    while (f[st]<=n)
    Ans+=dfs(st,inf);
    
    NEW(st,ed,Ans);
    NEW(ed,st,Ans);
    
    b[t+1]=1;
    d[t+1][1]=st;
    bz[st]=t+1;
    
    h2=0;t2=1;
    d2[1]=st;
    while (h2<t2)
    {
        for (i=ls[d2[++h2]]; i; i=a[i][1])
        if (a[i][2] && a[i^1][2] && bz[a[i][0]]==t)
        {
            d2[++t2]=a[i][0];
            bz[a[i][0]]=t+1;
            
            d[t+1][++b[t+1]]=a[i][0];
        }
    }
    work(t+1);
    
    b[t+1]=0;
    fo(i,1,b[t])
    if (bz[d[t][i]]==t+1)
    bz[d[t][i]]=t;
    else
    if (bz[d[t][i]]==t)
    {
        d[t+1][++b[t+1]]=d[t][i];
        bz[d[t][i]]=t+1;
    }
    
    work(t+1);
    fo(i,1,b[t])
    if (bz[d[t][i]]==t+1)
    bz[d[t][i]]=t;
}

void swap(int &x,int &y)
{
    int z=x;
    x=y;
    y=z;
}

int js(int x,int y)
{
    int i,ans=inf;
    
    if (D[x]<D[y])
    swap(x,y);
    
    fd(i,8,0)
    if (D[fa[x][i]]>=D[y])
    ans=min(ans,mn[x][i]),x=fa[x][i];
    
    fd(i,8,0)
    if (fa[x][i]!=fa[y][i])
    ans=min(ans,min(mn[x][i],mn[y][i])),x=fa[x][i],y=fa[y][i];
    
    if (x!=y) ans=min(ans,min(mn[x][0],mn[y][0]));
    return ans;
}

void Dfs(int Fa,int t)
{
    int i;
    
    fa[t][0]=Fa;
    D[t]=D[Fa]+1;
    fo(i,1,8)
    fa[t][i]=fa[fa[t][i-1]][i-1],mn[t][i]=min(mn[t][i-1],mn[fa[t][i-1]][i-1]);
    
    for (i=Ls[t]; i; i=aa[i][1])
    if (aa[i][0]!=Fa)
    {
        mn[aa[i][0]][0]=aa[i][2];
        Dfs(t,aa[i][0]);
    }
}

int main()
{
//  freopen("luogu4897.in","r",stdin);
    
    scanf("%d%d",&n,&m);len=1;++n;
    fo(i,1,m)
    {
        scanf("%d%d%d",&j,&k,&l);
        ++j;++k;
        
        New(j,k,l);
        New(k,j,l);
    }
    
    b[0]=n;
    fo(i,1,n)
    d[0][i]=i;
    return 0;
    work(0);
    Dfs(0,1);
    
    scanf("%d",&Q);
    for (;Q;--Q)
    {
        scanf("%d%d",&x,&y);++x;++y;
        printf("%d\n",js(x,y));
    }
}
上一篇:[洛谷P5180][模板]支配树


下一篇:Codeforces Global Round 6D(VECTOR >)