二分图

1. 判定 (染色法)

#include<bits/stdc++.h>
using namespace std;
const int N = 100010, M = 200010;
int n, m;
int g[N], cnt, color[N];
struct node{
    int nxt,to;
}e[M];
bool st[N];
void ins(int a, int b){
    cnt ++;
    e[cnt].to = b;
    e[cnt].nxt = g[a];
    g[a] = cnt;
}
bool dfs(int x, int c){
    color[x] = c;
    for (int i = g[x]; i; i = e[i].nxt){
        int j = e[i].to;
        if (!color[j]){
            if (!dfs(j, 3 - c)) return false;
        }
        else if (color[j] == c) return false;  
    }
    return true;
}
int main(){
    scanf("%d%d", &n, &m);
    for (int i = 1; i <= m; i++){
        int a, b;
        scanf("%d%d", &a,&b);
        ins (a, b); ins(b, a);
    }
    
    bool flag = true;
    for (int i = 1; i <= n; i++)
        if(!color[i]){
            if(!dfs(i,1)){
                flag = 0;
                break; 
            }
        }
    
    if(flag)puts("Yes");
    else puts("No");
    return 0;
}
    

例题 

洛谷 p1525 关押罪犯

#include<bits/stdc++.h>
using namespace std;
const int N = 20010, M = 200010;
int n, m;
int g[N], cnt, color[N], ans;
struct node{
    int nxt, to, w;
}e[M];
bool st[N];
void ins(int a, int b, int w){
    cnt ++;
    e[cnt].to = b;
    e[cnt].nxt = g[a];
    e[cnt].w = w;
    g[a] = cnt;
}
bool dfs(int x, int c, int mid){
    color[x] = c;
    for (int i = g[x]; i; i = e[i].nxt){
        int j = e[i].to;
        if (e[i].w <= mid) continue;
        if (color[j]){
            if (color[j] == c) return false;
        }
        else if (!dfs(j, 3 - c, mid))return false;  
    }
    return true;
}
bool check(int mid){
    memset(color, 0, sizeof(color));
    for (int i = 1; i <= n; i++)
        if (color[i] == 0)
            if(!dfs(i, 1, mid)) return false;
            return true;
}
int main(){
    scanf("%d%d", &n, &m);
    for (int i = 1; i <= m; i++){
        int a, b, w;
        scanf("%d%d%d", &a, &b, &w);
        ins (a, b, w); ins(b, a, w);
    }
    int l = 0, r = 1e9;
    while(l <= r){
        int mid = (l + r) >> 1;
        if (check(mid)) ans = mid, r = mid - 1;
        else l = mid + 1;
    }
    
    printf ("%d", ans);
    return 0;
}
    

2 二分图的最大匹配 (匈牙利算法)

#include<bits/stdc++.h>
using namespace std;
const int N = 100010, M = 200010;
int n1, n2, m;
int g[N], cnt, match[N];
struct node{
    int nxt,to;
}e[M];
bool st[N];
void ins(int a, int b){
    cnt ++;
    e[cnt].to = b;
    e[cnt].nxt = g[a];
    g[a] = cnt;
}
bool find(int x){
    for (int i = g[x]; i; i = e[i].nxt){
        int j = e[i].to;
        if (!st[j]){
            st[j] = true;
            if (match[j] == 0|| find(match[j])){
                 match[j] = x;
                 return true;
            }    
        }
    }
    return false;
}
int main(){
    scanf("%d%d%d", &n1, &n2, &m);
    for (int i = 1; i <= m; i++){
        int a, b;
        scanf("%d%d", &a,&b);
        ins (a, b); 
    }
    
    int res = 0;
    for (int i = 1; i <= n1; i++){
        memset(st, false, sizeof(st));
        if(find(i)) res++;
    }
    
    printf("%d", res);
    return 0;
}
    

例题  洛谷 p3386

#include<bits/stdc++.h>
using namespace std;
const int N = 100010, M = 200010;
int n1, n2, m;
int g[N], cnt, match[N];
struct node{
    int nxt,to;
}e[M];
bool st[N];
void ins(int a, int b){
    cnt ++;
    e[cnt].to = b;
    e[cnt].nxt = g[a];
    g[a] = cnt;
}
bool find(int x){
    for (int i = g[x]; i; i = e[i].nxt){
        int j = e[i].to;
        if (!st[j]){
            st[j] = true;
            if (match[j] == 0|| find(match[j])){
                 match[j] = x;
                 return true;
            }    
        }
    }
    return false;
}
int main(){
    scanf("%d%d%d", &n1, &n2, &m);
    for (int i = 1; i <= m; i++){
        int a, b;
        scanf("%d%d", &a,&b);
        ins (a, b); 
    }
    
    int res = 0;
    for (int i = 1; i <= n1; i++){
        memset(st, false, sizeof(st));
        if(find(i)) res++;
    }
    
    printf("%d", res);
    return 0;
}
    

 

posted @ 2023-11-14 20:20  nameko  阅读(26)  评论(0)    收藏  举报