二分图匹配的小总结

二分图匹配

  • 二分图:分为两个点集,左点集内部各点之间没有边,右点集同样
  • 判断是否为二分图:染色法判断:
    • 给一个点染色,给与它相连的点染另一个颜色,如果有冲突那就不是二分图
  • 最大匹配
    • 能够匹配最多顶点(每个顶点只能匹配一次)
  • 完美匹配
    • 所有顶点都能匹配,完美匹配就是最大匹配
  • 最小顶点覆盖
    • 用最少的顶点覆盖最多的边
    • 最小顶点覆盖 = 最大匹配
  • 最大独立集
    • 两两之间没有边的顶点集合
    • 最大独立集
      = 所有顶点数 - 最小顶点覆盖
      = 所有顶点数 - 最大匹配

      最大匹配:把边的利用最大化;每一条边的两个端点至少有一个能被匹配
      独立集:点与点之间 不存在边,(如果有边肯定能匹配上)

1. 匈牙利算法

#include <bits/stdc++.h>
using namespace std;

int st[550][550];//邻接矩阵
int net[550],used[550];
int k,n,m;

int fin(int x)
{
    for(int i=1;i<=m;i++)
    {
        if(st[x][i]&&!used[i])
        {
            used[i]=1;
            if(net[i]==0||fin(net[i]))
            {
                net[i]=x;
                return 1;
            }
        }
    }
    return 0;
}

int match()
{
    int sum=0;
    for(int i=1;i<=n;i++)
    {
        memset(used,0,sizeof(used));
        if(fin(i)) sum++;
    }
    return sum;

}

int main()
{
    ios::sync_with_stdio(false);
    while(cin>>k&&k)
    {
        memset(st,0,sizeof(st));
        memset(net,0,sizeof(net));
        cin>>n>>m;
        for(int i=1;i<=k;i++)
        {
            int x,y;
            cin>>x>>y;
            st[x][y]=1;
        }
        cout<<match()<<endl;
    }

    return 0;
}

2.染色体匹配 + 匈牙利算法

The Accomodation of Students: https://vjudge.net/problem/HDU-2444
题解

#include <bits/stdc++.h>
#include <vector>
using namespace std;
int n,m;
vector <int> st[205];
int color[205],used[205],net[205];

int judge(int x,int co)//染色
{
    color[x]=co;
    int t=st[x].size();
    for(int i=0; i<t; i++)
    {
        int v=st[x][i];
        if(color[v]==0&&judge(v,3-co))
            return 1;
        else if(color[v]!=3-co)
        {
            cout<<"No"<<endl;
            return 1;
        }
    }
    return 0;
}

int f2(int x)//匈牙利算法
{
    int t=st[x].size();
    for(int i=0; i<t; i++)
    {
        int v=st[x][i];
        if(!used[v])
        {
            used[v]=1;
            if(net[v]==0||f2(net[v]))
            {
                net[v]=x;
                return 1;
            }
        }
    }
    return 0;
}

void solve()
{
    int sum=0;
    for(int i=1; i<=n; i++)
    {
        if(color[i]==0&&judge(i,1))
            return ;
    }
    for(int i=1; i<=n; i++)
    {
        memset(used,0,sizeof(used));
        if(f2(i)) sum++;
    }
    cout<<sum<<endl;
}

int main()
{
    ios::sync_with_stdio(false);
    while(cin>>n>>m)
    {
        for(int i=0; i<=205; i++)
            st[i].clear();
        memset(color,0,sizeof(color));
        memset(net,0,sizeof(net));
        for(int i=0; i<m; i++)
        {
            int x,y;
            cin>>x>>y;
            st[x].push_back(y);
        }
        solve();
    }
    return 0;
}

3
Cat VS Dog:https://vjudge.net/problem/HDU-3829
建立无向图 最大匹配结果需要除以2

#include <bits/stdc++.h>
#include <vector>
using namespace std;
pair <string,string> cd;
string x[520],y[520];
int st[550][550],vis[550],pre[550];
int n,m,p;
int sum=0;
void init()
{
    sum=0;
    memset(st,0,sizeof(st));
    memset(pre,0,sizeof(pre));
}

int fin(int x)
{
    for(int i=1; i<=p; i++)
    {
        if(st[x][i]&&vis[i]==0)
        {
            vis[i]=1;
            if(pre[i]==0||fin(pre[i]))
            {
                pre[i]=x;
                return 1;
            }
        }
    }
    return 0;
}

void solve()
{
    for(int i=1; i<=p; i++)
    {
        memset(vis,0,sizeof(vis));
        if(fin(i))sum++;
    }
}

int main()
{
    ios::sync_with_stdio(false);

    while(cin>>n>>m>>p)
    {
        init();
        for(int i=1; i<=p; i++)
        {
            cin>>x[i]>>y[i];

            for(int j=1; j<=i; j++)
            {
                if(x[i]==y[j]||y[i]==x[j])
                    st[i][j]=st[j][i]=1; //无向图
            }
        }
        solve();
        cout<<p-sum/2<<endl;
   	}

    return 0;
}

4. Swap Free // Team Contest - 1

Swap Free:https://vjudge.net/contest/418417#problem/D
Swap Free:https://codeforces.com/gym/102423/problem/D
完整题目链接:https://codeforces.com/gym/102423/attachments/download/9792/2019-SER-D1-Problems.pdf

求最大独立集

Time limit: 1 second

A set of words is called swap free if there is no way to turn any word in the set into any other word in the set by swapping only a single pair of (not necessarily adjacent) letters.
You are given a set of 𝒏 words that are all anagrams of each other. There are no duplicate letters in any word. Find the size of the largest swap free subset of the given set. Note that it is possible for the largest swap free subset of the given set to be the set itself.
Input
The first line of input contains a single integer 𝒏 (1 ≤ 𝒏 ≤ 500).
Each of the next 𝒏 lines contains a single word 𝒘 (1 ≤ |𝒘| ≤ 26).
Every word contains only lower-case letters and no duplicate letters. All 𝒏 words are unique, and every
word is an anagram of every other word.
Output
Output a single integer, which is the size of the largest swap free subset.

Sample Input
6
abc
acb
cab
cba
bac
bca
Sample Output
3

Sample Input
11
alerts
alters
artels
estral
laster
ratels
salter
slater
staler
stelar
talers
Sample Output
8

Sample Input
6
ates
east
eats
etas
sate
teas
Sample Output
4

题意:找出集合中任意一个串交换两个字符不能变成另外一个串的 所有串的集合。
最大独立集

#include <bits/stdc++.h>
using namespace std;
string a[550];
//int st[550][550];
int vis[550],pre[550];
int n;
vector<int>st[555];

int fin(int x)
{
    for(int i=0;i<st[x].size();i++)
    {
        int u=st[x][i];
        if(vis[u]==0)
        {
            vis[u]=1;
            if(pre[u]==0||fin(pre[u]))
            {
               // cout<<x<<" ---"<<u<<endl;
                pre[u]=x;
                return 1;
            }
        }
    }
    return 0;
}


int match()
{
    int sum=0;
    for(int i=1;i<=n;i++)
    {
        memset(vis,0,sizeof(vis));
        if(fin(i)) sum++;
    }
    return sum;
}

int main()
{
    ios::sync_with_stdio(false);
    memset(pre,0,sizeof(pre));
    cin>>n;
    for(int i=1;i<=n;i++) cin>>a[i];
    for(int i=1;i<=n;i++)
    {
        for(int j=i+1;j<=n;j++)
        {
             int num=0;
            for(int li=0;li<a[i].size();li++)
            {
                if(a[i][li]!=a[j][li]) num++;
                if(num>2) break;
            }
             if(num==2) st[i].push_back(j),st[j].push_back(i);
        }
    }

    cout<<n-(match()/2)<<endl;

    return 0;
}
  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
GS算法和二分图匹配算法都是用于解决匹配问题的算法。二分图匹配算法是一种通用的算法,用于解决二分图中的匹配问题。而GS算法则是二分图匹配算法的一个特殊案例。 GS算法是基于婚姻匹配问题的研究而提出的。它的核心原理是男生按照自己喜好的顺序向女生发起追求,并尽可能形成稳定的匹配。如果有更好的匹配出现,就会断开之前的匹配,并与新的匹配对象建立关系。 二分图匹配算法则是一种更一般化的算法,适用于解决二分图中的匹配问题。它的原理也是通过不断调整匹配关系,使得每个节点都能够得到匹配。不同于GS算法,二分图匹配算法并没有定义匹配的好坏,只关注是否存在匹配总结来说,GS算法是二分图匹配算法的一个特例,它专门用于解决婚姻匹配问题,而二分图匹配算法则适用于一般的二分图匹配问题。两者的核心原理是类似的,都是通过调整匹配关系来达到稳定的匹配状态。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [详解匈牙利算法与二分图匹配](https://blog.csdn.net/wangxiao7474/article/details/111945752)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值