二分图的模板

Posted linhaitai

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了二分图的模板相关的知识,希望对你有一定的参考价值。

博客:

匈牙利算法模板:

技术分享图片
#include<bits/stdc++.h>
#define MAXN 9999
using namespace std;
int nx,ny;//nx表示二分图左边顶点的个数,ny表示二分图右边顶点的个数
int m;//m代表边的条数
int cx[MAXN],cy[MAXN];//如果有cx[i]=j,则必有cy[j]=i,说明i点和j点能够匹配
int x,y;//x点到y点有边
int e[MAXN][MAXN];//邻接矩阵
int visited[MAXN];//标记数组,标记的永远是二分图右边的顶点
int ret;//最后结果
int point(int u)//这个函数的作用是寻找增广路和更新cx,xy数组,如果找到了增广路,函数返回1,找不到,函数返回0。
{
    for(int v=1;v<=ny;v++)//依次遍历右边的所有顶点
    {
        if(e[u][v]&&!visited[v])//条件一:左边的u顶点和右边的v顶点有连通边,
//条件二:右边的v顶点在没有被访问过,这两个条件必须同时满足
        {
            visited[v]=1;//将v顶点标记为访问过的
            if(cy[v]==-1||point(cy[v]))//条件一:右边的v顶点没有左边对应的匹配的点,
            {//条件二:以v顶点在左边的匹配点为起点能够找到一条增广路(如果能够到达条件二,说明v顶点在左边一定有对应的匹配点)。
                cx[u]=v;//更新cx,cy数组
                cy[v]=u;
                return 1;
            }
        }
    }
    return 0;//如果程序到达了这里,说明对右边所有的顶点都访问完了,没有满足条件的。
}
int main()
{
    while (cin>>m>>nx>>ny)
    {
        memset(cx,-1,sizeof(cx));//初始化cx,cy数组的值为-1
        memset(cy,-1,sizeof(cy));
        memset(e,0,sizeof(e));//初始化邻接矩阵
        ret=0;
        while (m--)//输入边的信息和更新邻接矩阵
        {
            cin>>x>>y;
            e[x][y]=1;
        }
        for(int i=1;i<=nx;i++)//对二分图左边的所有顶点进行遍历
        {
            if(cx[i]==-1)//如果左边的i顶点还没有匹配的点,就对i顶点进行匹配
            {
                memset(visited,0,sizeof(visited));//每次进行point时,都要对visited数组进行初始化
                ret+=point(i);//point函数传入的参数永远是二分图左边的点
            }
        }
        cout<<ret<<endl;
    }

}
View Code

例题:hdu 1083

代码:

技术分享图片
#include<iostream>
#include<iostream>
#include<stdio.h>
#include<string.h>
using namespace std;
const int max_n=105,max_m=305;
bool edge[max_n][max_m],vis[max_m];
int cx[max_n],cy[max_m];
int n,m;
int pointn(int u)
{
    for(int v=1;v<=m;v++)
    {
        if(edge[u][v]==1&&vis[v]==0)
        {
            vis[v]=1;
            if(cy[v]==-1||pointn(cy[v]))
            {
                cx[u]=v;
                cy[v]=u;
                return 1;
            }
        }
    }
    return 0;
}
int main()
{
    int  t;
    scanf("%d",&t);
    while(t--)
    {
        int res=0;
        //cout<<res<<endl;
        memset(cx,-1,sizeof(cx));
        memset(cy,-1,sizeof(cy));
        memset(edge,0,sizeof(edge));
        scanf("%d %d",&n,&m);
        for(int i=1;i<=n;i++)
        {
            int k;
            scanf("%d",&k);
            for(int j=0;j<k;j++)
            {
                int x;
                scanf("%d",&x);
                edge[i][x]=1;
            }
        }
        for(int i=1;i<=n;i++)
        {
             if(cx[i]==-1)
             {
                   memset(vis,0,sizeof(vis));
               res+=pointn(i);

             }

              // cout<<res<<endl;
        }
        if(res==n)
            printf("YES
");
        else
            printf("NO
");
    }
    return 0;
}
View Code

 

以上是关于二分图的模板的主要内容,如果未能解决你的问题,请参考以下文章

二分图的模板

二分图的最大匹配(模板)

二分图的判定(染色法)和二分图最大匹配(匈牙利)算法及模板

匈牙利 算法&模板

匈牙利算法,二分图的最大匹配

二分图模板