Método bipartito de coloración de gráficos y algoritmo húngaro

Grafo bipartito: el grafo no dirigido de n orden G es un grafo bipartito si y solo si no hay un ciclo impar en G.

Método de tinción

Idea: Definido por un gráfico bipartito. Para cada borde del gráfico, sus puntos finales están en conjuntos diferentes. Por lo tanto, para cada conexión rápida en el gráfico, puede usar dfs para marcar cada punto en el gráfico. Si hay puntos contradictorios, el gráfico No es un gráfico bipartito. La complejidad del tiempo es O (n + M).

#include <iostream>
#include <cstring>

using namespace std;

const int N = 100010, M = 200010;
int e[M], ne[M], h[N], idx;
int color[N];
int n, m;

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

bool dfs(int now, int c)
{
    
    
    color[now] = c;
    for(int i = h[now]; i != -1; i = ne[i])
    {
    
    
        int j = e[i];
        if(color[j] == c) return false; 
        if(!color[j] && !dfs(j, -c)) return false;   
    }  
    return true;
}

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

Algoritmo de Hungría

Idea:
para los conjuntos de puntos v1 y v2 del gráfico bipartito, si desea el número máximo de bordes coincidentes, puede usar una tabla de adyacencia para almacenar los puntos de v2 a los que cada punto de v1 puede acceder, y usar una matriz para almacenar los puntos de v1 con los que cada punto de v2 coincide actualmente. Atraviese cada punto v1. Si el punto del conjunto v2 encontrado no está ocupado, utilícelo. Si ya está ocupado, vea si se puede cambiar el punto del conjunto v1 que ocupa el punto. Complejidad de tiempo O (nm)
Nota: Se debe utilizar una matriz para registrar si se accede al punto v2, de lo contrario, puede haber varios puntos en v1 "compitiendo" por un punto en v2, lo que da como resultado un bucle sin fin.

#include <iostream>
#include <cstring>
using namespace std;
const int N = 510, M = 100010;
int h[N], e[M], ne[M], idx; // 用链表记录左半部分各点所能到达的点
int match[N]; // 记录右半部分各点所匹配到左半部分的点
bool vis[N]; // 用于判断左边点是否被访问,反正某点被重复改变出现死循环
int n1, n2, m;

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

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

int main()
{
    
    
    memset(h, -1, sizeof h);
    cin >> n1 >> n2 >> m;

    int l, r;
    for (int i = 0; i < m; i++)
    {
    
    
        cin >> l >> r;
        add(l, r);
    }
    
    int ans = 0;

    for(int i = 1; i <= n1; i++)
    {
    
    
        memset(vis, false, sizeof vis);
        if(find(i)) ans++;
    }

    cout << ans;
    return 0;
}

Supongo que te gusta

Origin blog.csdn.net/PBomb/article/details/107774631
Recomendado
Clasificación