图论模板(最小生成树、二分图)

一、Prim

题意

求最小生成树

代码

int prim()
{
    
    
    memset(dist,0x3f,sizeof(dist));
    int res = 0;
    for(int i=0;i<n;i++){
    
    
        int t= -1;
        for(int j=1;j<=n;j++){
    
    
            if(!st[j]&&(t==-1||dist[t]>dist[j])){
    
    
                t = j;
            }
        }
        st[t] = true;
        if(i&&dist[t]==inf) return inf;
        if(i) res += dist[t];
        for(int j=1;j<=n;j++){
    
    
            dist[j] = min(dist[j], g[t][j]);
        }
    }
    return res;
}

二、Kruskal

题意

求最小生成树

代码

struct Edge
{
    
    
    int a,b,w;
    bool operator < (const Edge &W) const
    {
    
    
        return w < W.w;
    }
}edges[M];

int find(int x)
{
    
    
    if(x!=p[x]) p[x] = find(p[x]);
    return p[x];
}


int kruskal()
{
    
    
    sort(edges,edges+m);
    for(int i=1;i<=n;i++) p[i] = i;
    int res = 0, cnt = 0;
    for(int i=0;i<m;i++){
    
    
        auto e = edges[i];
        int a = e.a, b = e.b, w = e.w;
        a = find(a), b = find(b);
        if(a!=b){
    
    
            p[a] = b;
            res += w;
            cnt ++;
        }
    }
    if(cnt<n-1) return inf;
    else return res;
}

三、染色法判断二分图

题意

判断一个图是否为二分图

代码

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>

using namespace std;

const int N = 100010, M = 200010, inf = 0x3f3f3f3f;

int n, m;
int h[N], e[M], ne[M], idx;
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]==color[u]) return false;
    }
    return true;
}

int main()
{
    
    
    memset(h,-1,sizeof(h));
    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;
}

四、匈牙利算法

题意

求二分图最大匹配

代码

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>

using namespace std;

const int N = 100010, M = 200010;

int n1,n2,m;
int h[N], e[M], ne[M], idx;
int match[N];
bool st[N];

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;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()
{
    
    
    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;
}

猜你喜欢

转载自blog.csdn.net/weixin_43634220/article/details/108544888