[BZOJ]4405: [wc2016]挑战NPC(带花树)

带花树模板

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
inline int read()
{
    int x;char c;
    while((c=getchar())<'0'||c>'9');
    for(x=c-'0';(c=getchar())>='0'&&c<='9';)x=x*10+c-'0';
    return x;
}
#define MN 600
#define ME 100000
#define ms(a) memset(a,0,sizeof(a))
struct edge{int nx,t;}e[ME*2+5];
int h[MN+5],en,mat[MN+5],nx[MN+5],mk[MN+5],f[MN+5],q[MN+5],qn,u[MN+5],cnt;
inline void ins(int x,int y)
{
    e[++en]=(edge){h[x],y};h[x]=en;
    e[++en]=(edge){h[y],x};h[y]=en;
}
int gf(int k){return f[k]?f[k]=gf(f[k]):k;}
int lca(int x,int y)
{
    for(++cnt;;swap(x,y))if(x)
    {
        x=gf(x);
        if(u[x]==cnt)return x;
        u[x]=cnt;
        x=nx[mat[x]];
    }
}
void group(int x,int r)
{
    while(x!=r)
    {
        int a=mat[x],b=nx[a];
        if(gf(b)!=r)nx[b]=a;
        if(mk[a]>1)mk[q[++qn]=a]=1;
        if(mk[b]>1)mk[q[++qn]=b]=1;
        if(gf(x)!=gf(a))f[gf(x)]=gf(a);
        if(gf(a)!=gf(b))f[gf(a)]=gf(b);
        x=b;
    }
}
bool aug(int x)
{
    int i,j,y,r;
    ms(nx);ms(mk);ms(f);
    for(mk[q[i=qn=0]=x]=1;i<=qn;++i)for(j=h[x=q[i]];j;j=e[j].nx)
    {
        y=e[j].t;
        if(mat[x]==y||gf(x)==gf(y)||mk[y]>1)continue;
        if(mk[y])
        {
            r=lca(x,y);
            if(gf(x)!=r)nx[x]=y;
            if(gf(y)!=r)nx[y]=x;
            group(x,r);group(y,r);
        }
        else if(!mat[y])
        {
            for(nx[y]=x,i=y;i;i=y)
            {
                x=nx[i];y=mat[x];
                mat[i]=x;mat[x]=i;
            }
            return true;
        }
        else
        {
            nx[y]=x;mk[y]=2;
            mk[q[++qn]=mat[y]]=1;
        }
    }
    return false;
}
int main()
{
    int T=read(),n,m,e,x,y;
    while(T--)
    {
        n=read();m=read();e=read();
        ms(h);en=0;ms(mat);
        for(x=1;x<=m;++x)ins(n+(x-1)*3+1,n+(x-1)*3+2);
        while(e--)
        {
            x=read();y=read();
            ins(x,n+(y-1)*3+1);
            ins(x,n+(y-1)*3+2);
            ins(x,n+(y-1)*3+3);
        }
        for(x=1,y=-n;x<=n+3*m;++x)if(!mat[x]&&aug(x))++y;
        printf("%d
",y);
    }
}
原文地址:https://www.cnblogs.com/ditoly/p/BZOJ4405.html