加载中...

二分图

\[二分图 \begin{cases} \ 染色法 \\[4ex] 匈牙利算法 \end{cases}\ \]



染色法

//染色法判别二分图模板

int n;		//n表示点数
int h[N],e[M],ne[M],idx;	//邻接表存储图
int color[N];		//表示每个点的颜色,-1表示为染色,0表示白色,1表示黑色

//参数:u表示当前节点,c表示当前点的颜色
bool dfs(int u  int c)
{
    color[u]=c;
    for(int i=h[u];i!=-1;i=ne[i])
    {
        int j=e[i];
        if(color[j]==-1)
        {
            if(!dfs(j,!c))return false;
        }
        else if(color[j]==c)return false;
    }
    return true;
}

bool check()
{
    memset(color,-1,sizeof color);
    bool flag=true;
    for(int i=1;i<=n;i++)
        if(color[i]==-1)
            if(!dfs(i,0))
            {
                flag=false;
                break;
            }
    return flag;
}



匈牙利算法

//匈牙利算法模板

int n1,n2;		//n1表示第一个集合中的点数,n2表示第二个集合中的点数
int h[N],e[M],ne[M],idx;	//匈牙利算法中只会用到从第一个集合指向第二个集合的边
int match[N];		//存储第二个集合中的每个点当前匹配的第一个集合中的点是哪个
bool st[N];			//表示第二个集合中的每个点是否已经被遍历过

bool find(int x)
{
    for(int i=h[x];i!=-1;i=ne[i])
    {
        int j=e[i];
        if(!st[j])
        {
            st[j]=true;
            if(match[j]==0||find(match[j]))
            {
                match[j]=x;
                return true;
            }
        }
    }
    
    return false;
}

//求最大匹配数,依次枚举第一个集合中的每个点能否匹配第二个集合中的点
int res=0;
for(int i=1;i<=n;i++)
{
    memset(st,false,sizeof st);
    if(find(i))res++;
}


posted @ 2023-04-28 16:38  邪童  阅读(2)  评论(0编辑  收藏  举报