##二分图##

~~~~~~~~~~~~~~~~~~~~~~~~~~~以下是最大匹配~~~~~~~~~~~~~~~~~~~~~~~~~~~~

参考:http://blog.csdn.net/hackbuteer1/article/details/7398008

点覆盖数+点独立数=n

边覆盖数+边独立数(匹配)=n

点覆盖数=边独立数(匹配)

//algo1:
//simplified_newflow
//O(n*m)
struct simplified_newflow{
    int nx,ny,m,ans;
    int cy[N],cx[N],vis[N];
    vector<int > G[N];
    void init(int x,int y)
    {
        nx=x; ny=y;
        for (int i=0;i<nx;i++) G[i].clear();
    }
    int path(int u)
    {   for (int i=0;i<G[u].size();i++)
        if (!vis[G[u][i]])
        {   int v=G[u][i];
            vis[v]=1;
            if (cy[v]==-1||path(cy[v]))
                {
                    cx[u]=v;
                    cy[v]=u;
                    return 1;
                }
        }
    return 0;
    }
    int MaxMatch()
    {   int ans=0;
        memset(cx,-1,sizeof(cx));
        memset(cy,-1,sizeof(cy));
        for (int i=0;i<nx;i++)
        if (cx[i]==-1)
        {   memset(vis,0,sizeof(vis));
            ans+=path(i);
        }
        return ans;
    }
}it;


//algo2:
//Hopcroft_Carp
//O(n^(1/2)*m)
struct Hopcroft_Carp{
    vector<int > g[N];
    int Mx[N],My[N],nx,ny;
    int dx[N],dy[N],dis;
    bool vst[N],T[N];
    void init(int x,int y)
    {
        nx=x; ny=y;
        for (int i=0;i<nx;i++)  g[i].clear();
    }
    void AddEdge(int u,int v)
    {
        g[u].pb(v);
    }
    bool searchP()
    {
        queue<int>Q; dis=INF;
        memset(dx,-1,sizeof(dx));
        memset(dy,-1,sizeof(dy));
        for(int i=0;i<nx;i++)
        if(Mx[i]==-1)
        {
            Q.push(i);
            dx[i]=0;
        }
        while(!Q.empty())
        {
        int u=Q.front();
        Q.pop();
        if(dx[u]>dis)  break;
        for(int i=0;i<g[u].size(); i++)
            if(dy[g[u][i]]==-1)
            {   int v=g[u][i];
                dy[v]=dx[u]+1;
                if(My[v]==-1)  dis=dy[v];
                else
                {
                    dx[My[v]]=dy[v]+1;
                    Q.push(My[v]);
                }
            }
        }
        return dis!=INF;
    }
    bool DFS(int u)
    {
        for(int i=0;i<g[u].size(); i++)
        {   int v=g[u][i];
            if(vst[v]||dy[v]!=dx[u]+1)continue;
            vst[v]=1;
            if(My[v]!=-1&&dy[v]==dis) continue;
            if(My[v]==-1||DFS(My[v]))
           {
               My[v]=u;
               Mx[u]=v;
               return 1;
           }
       }
        return 0;
    }
    int MaxMatch()
    {
        int res=0;
        memset(Mx,-1,sizeof(Mx));
        memset(My,-1,sizeof(My));
        while(searchP())
        {
        memset(vst,0,sizeof(vst));
        for(int i=0;i<nx;i++)
          if(Mx[i]==-1&&DFS(i))  res++;
        }
        return res;
    }
}it;


~~~~~~~~~~~~~~~~~~~~~~~~~~~以下是最大权匹配~~~~~~~~~~~~~~~~~~~~~~~~~~~~

//KM最大权匹配模板:
//[建议]求最小权方法一:Addedge边取反且最后答案取反
//求最小权方法二:按注释@……@部分改
typedef double typ;
const typ INF=1e8;
struct KM_{
    int nx,ny;
    typ E[?][?],lx[N],ly[N],slk[N];
    int link[N],lin[N];
    bool visx[N],visy[N];
    bool DFS(int u)
    {
        visx[u]=true;
        for(int v=0;v<ny;++v)
        {
            if(visy[v])continue;
            typ t=lx[u]+ly[v]-E[u][v];
            if(t>eps)     //t>0   如果typ为int
                          //@t<-eps@
                {minimize(slk[v],t);continue;}  //@maximize@
            visy[v]=1;
            if(link[v]==-1||DFS(link[v])){link[v]=u;lin[u]=v;return true;}
        }
        return false;
    }
    typ KM()
    {
        CLR(ly,0);
        CLR(link,-1);
        CLR(lin,-1);
        for(int i=0;i<nx;++i)lx[i]=*max_element(E[i],E[i]+ny);//@min_element@
        for(int u=0;u<nx;++u)
        {   fill_n(slk,ny,INF); //@fill_n(slk,ny,-INF);@
            while(1)
            {
                CLR(visx,0);
                CLR(visy,0);
                if(DFS(u))break;
                typ temp=INF;  //temp=-INF;@
                for(int v=0;v<ny;++v)if(!visy[v]) minimize(temp,slk[v]); //@maximize@
                 if (temp==INF) return (#-1#);
                for(int i=0;i<nx;++i)if(visx[i])lx[i]-=temp;
                for(int v=0;v<ny;++v)if(visy[v])ly[v]+=temp;else slk[v]-=temp;
            }
        }
    typ ret=0;
    for(int j=0;j<nx;++j)if (lin[j]!=-1)ret+=E[j][lin[j]];
    return ret;
    }
    void init(int x,int y)
    {   nx=x; ny=y;
        CLR(E,0);
    }
    void AddEdge(int x,int y,typ z)
    {   E[x][y]=z;
    }
}it;










~~~~~~~~~~~~~~~~~~~~~~~~~~~以下是带匹配数限制的最大权匹配~~~~~~~~~~~~~~~~~~~~~~~~~~~~

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值