acwing——二分图

1.染色法判断二分图

二分图:如果点集V可以被划分成两个互不相交的点集,并且这个图中的所有边的两个顶点分别属于两个不同的点集,则称该图为二分图。

奇数环:由奇数条边组成的环。

如果一条边的一个顶点属于点集V,那么另一个点必属于点集W。如果存在奇数环,那么就会存在矛盾。

判断:只要没有奇数环,就是二分图。

#include <iostream>
#include <cstring>

using namespace std;

const int N = 200010 , M = 100010;

int idx , e[N] , ne[N] , h[N];
int color[N];

void add(int a , int b)
{
    e[idx] = b , ne[idx] = h[a] , h[a] = idx++;
}

bool dfs(int u , int c)
{
    color[u] = c;
    
    for(int i = h[u] ; ~i ; i = ne[i])
    {
        int j = e[i];
        if(!color[j])
        {
            if(!dfs(j , 3 - c))  return false;
        }
        else
        {
            if(color[j] == c)   return false;
        }
    }
    
    return true;
}

int main()
{
    memset(h , -1 , sizeof h);
    
    int n , m;
    cin >> n >> m;
    
    while(m--)
    {
        int a , b;
        cin >> a >> b;
        add(a , b) , add(b , a);
    }
    
    bool flag = true;
    for(int i = 1 ; i <= n ; i++)
    {
        if(!color[i])
        {
            if(!dfs(i , 1))
            {
                flag = false;
                break;
            }
        }
    }
    
    if(flag)    puts("Yes");
    else puts("No");
    return 0;
}

2.匈牙利算法

题目:
在这里插入图片描述可以类比成左边是一堆男生,右边是一堆女生。二分图可以看成如果点与点之间有连线,则男生对女生有好感,而匹配成功则可以看成有好感的男女成为情侣,男女。我们的任务是当一名月老,目的是使最多对男女成为情侣!

在存储时,因为我们用男生去匹配女生,因此要从男生指向女生。
在这里插入图片描述
最体现匈牙利算法神奇的一步!

#include <iostream>
#include <cstring>

using namespace std;

const int N = 510 , M = 100010;

int idx , h[N] , e[M] , ne[M];
int match[N];//和妹子成为情侣的男生
bool st[N];//妹子是否被匹配过

void add(int a , int b)
{
    e[idx] = b , ne[idx] = h[a] , h[a] = idx++;
}

int find(int x)
{
    for(int i = h[x] ; ~i ; i = ne[i])//遍历男生有好感的女生
    {
        int j = e[i];
        if(!st[j])//在新的一轮中女生未匹配过
        {
            st[j] = true;
            if(!match[j] || find(match[j]))//如果该女生没有对象或者这个女生的男朋友可以重新找一个
            {                              //
                match[j] = x;
                return true;
            }
        }
    }
    
    return false;
}

int main()
{
    int n1 , n2 , m;
    cin >> n1 >> n2 >> m;
    
    memset(h , -1 , sizeof h);
    
    while(m--)
    {
        int a, b;
        cin >> a >> b;
        add(a , b);
    }
    
    int res = 0;
    for(int i = 1 ; i <= n1 ; i++)
    {
       memset(st , false , sizeof st);
       if(find(i))  res++;
    }
    
    cout << res << endl;
    
    return 0;
}
发布了13 篇原创文章 · 获赞 3 · 访问量 330

猜你喜欢

转载自blog.csdn.net/Stephen_Zhao0/article/details/105300319