• luogu P6113 【模板】一般图最大匹配 带花树


    #include<bits/stdc++.h>
    #pragma GCC optimize(3)
    using namespace std;
    const int N=1009,M=100009;
    int n,m,ans,ord,q[M],pre[N];
    int ql,qr,dfn[N],lk[N];
    int cl[N],g[N];
    int e[M],ne[M],h[M],idx;
    void rd(int&x) //貌似加了快读瞬间加速近30ms,因此还是加了。
    {
        char c=getchar();
        x=0;
        while(c>57||c<48)c=getchar();
        while(c>47&&c<58)
            x+=(x<<3)+x+c-48,c=getchar();
    }
    int find(int x)
    {
        return g[x]==x?x:g[x]=find(g[x]);
    }
    void add(int a,int b)
    {
        e[idx]=b;
        ne[idx]=h[a];
        h[a]=idx++;
    }
    int lca(int x,int y)
    {
        for(++ord; x=find(x); swap(x,y))
            if(dfn[x]==ord)return x;//奇环编号相同,说明找到了。
            else dfn[x]=ord,x=pre[lk[x]];
    }
    void flw(int x,int y,int p) //开花。
    {
        while(find(x)!=p)
        {
            pre[x]=y,y=lk[x];
            if(cl[y]==2)cl[y]=1,q[++qr]=y;
            g[x]=p,g[y]=p,x=pre[y];
        }
    }
    bool dfs(int x)
    {
        for(int i=1; i<=n; ++i)g[i]=i;
        memset(cl,0,sizeof(cl));
        memset(pre,0,sizeof(pre));
        cl[q[ql=qr=1]=x]=1;//颜色为黑。
        for(int x=q[ql]; ql<=qr; x=q[++ql])
            for(int i=h[x],v,z; ~i; i=ne[i])
            {
                if(cl[v=e[i]]==2)continue;
                if(find(v)==find(x))continue;
                if(cl[v]==1)
                    z=lca(x,v),flw(x,v,z),flw(v,x,z);
                else if(!cl[v])
                {
                    cl[v]=2,pre[v]=x;
                    if(!lk[v])
                    {
                        for(int u=v,lst,y; u; u=lst)
                            lst=lk[y=pre[u]],lk[u]=y,lk[y]=u;//找到增广路了,一路取反。
                        return true;//答案+1。
                    }
                    cl[lk[v]]=1,q[++qr]=lk[v];//匹配它的点一定是黑点。
                }
            }
        return false;
    }
    int main()
    {
        memset(h,-1,sizeof h);
        scanf("%d%d",&n,&m);
        for(int u,v; m; --m)
            rd(u),rd(v),add(u,v),add(v,u);
        for(int i=1; i<=n; ++i)
            ans+=(!lk[i]&&dfs(i));
        printf("%d
    ",ans);
        for(int i=1; i<=n; ++i)
            printf("%d ",lk[i]);
        return 0*puts("");
    }
  • 相关阅读:
    POJ 1469 COURSES 二分图最大匹配
    POJ 1325 Machine Schedule 二分图最大匹配
    USACO Humble Numbers DP?
    SGU 194 Reactor Cooling 带容量上下限制的网络流
    POJ 3084 Panic Room 求最小割
    ZOJ 2587 Unique Attack 判断最小割是否唯一
    Poj 1815 Friendship 枚举+求最小割
    POJ 3308 Paratroopers 最小点权覆盖 求最小割
    1227. Rally Championship
    Etaoin Shrdlu
  • 原文地址:https://www.cnblogs.com/QingyuYYYYY/p/13034747.html
Copyright © 2020-2023  润新知