二分图匹配([洛谷]P3386 模板 二分图匹配)

二分图匹配其实十分简单,原理只有一个,能换则换,腾出这个妹子的位置,不要考虑其他人是不是很不满意从他喜欢中最喜欢的那一个变成了他喜欢中的最不喜欢的那一个,知道了这个原理,n遍DFS就可以过了:

#include<stdio.h>
#include<string.h>
const int Inf=1e9+10,maxn=5010,maxm=5010,maxe=10010;
int gi(){
    int sum=0,f=1;char ch=getchar();
    while(ch>'9' || ch<'0'){if(ch=='-')f=-1;ch=getchar();}
    while(ch<='9' && ch>='0'){sum=sum*10+ch-'0';ch=getchar();}
    return sum*f;
}
struct node{
    int to,next;
}e[maxe];
int cnt,front[maxn],use[maxn];
int used[maxm],b[maxm],n,m;
void Add(int u,int v){
    e[++cnt].to=v;
    e[cnt].next=front[u];
    front[u]=cnt;
}
bool dfs(int u){//寻找增广路
    for(int i=front[u];i;i=e[i].next)
        if(!used[e[i].to]){
            used[e[i].to]=1;
            if(b[e[i].to]==0 || dfs(b[e[i].to])){
                use[u]=e[i].to;
                b[e[i].to]=u;
                return true;
            }
        }
    return false;
}
int ED(){
    int ans=0;
    for(int i=1;i<=n;i++)
        if(!use[i]){
            memset(used,0,sizeof(used));
            if(dfs(i))ans++;
        }
    return ans;
}
int main(){
    int i,j,k,e;
    scanf("%d%d%d",&n,&m,&e);
    for(i=1;i<=e;i++){
        int u=gi(),v=gi();
        if(u<=n && v<=m)Add(u,v);
    }
    printf("%d\n",ED());
    return 0;
}

以上为邻接表版本,如果有需要的,以下是邻接矩阵版本

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<math.h>
#include<algorithm>
using namespace std;
int n,m;
int g[1010][1010];
int flag[1010],b[1010];
bool dfs(int u);
int ED();
void init();
int main(){
    init();
    return 0;
}
void init(){
    int i,j,k,e;
    scanf("%d%d%d",&n,&m,&e);
    for(i=1;i<=e;i++){
        int u,v;
        scanf("%d%d",&u,&v);
        if(u>n  || v>m)continue;
        g[u][v]=1;
    }
    printf("%d\n",ED());
}
int ED(){
    int ans=0;
    for(int i=1;i<=n;i++){
        memset(flag,0,sizeof(flag));
        if(dfs(i))ans++;
    }
    return ans;
}
bool dfs(int u){
    for(int v=1;v<=m;v++)
        if(g[u][v] && !flag[v]){
            flag[v]=1;
            if(!b[v] || dfs(b[v])){
                b[v]=u;
                return true;
            }
        }
    return false;
}
时间: 2024-07-29 01:54:11

二分图匹配([洛谷]P3386 模板 二分图匹配)的相关文章

AC日记——【模板】二分图匹配 洛谷 P3386

题目背景 二分图 题目描述 给定一个二分图,结点个数分别为n,m,边数为e,求二分图最大匹配数 输入输出格式 输入格式: 第一行,n,m,e 第二至e+1行,每行两个正整数u,v,表示u,v有一条连边 输出格式: 共一行,二分图最大匹配 输入输出样例 输入样例#1: 1 1 1 1 1 输出样例#1: 1 说明 n,m<=1000,1<=u<=n,1<=v<=m 因为数据有坑,可能会遇到v>m的情况.请把v>m的数据自觉过滤掉. 算法:二分图匹配 思路: 二分图模

【洛谷 p3386】模板-二分图匹配(图论)

题目:给定一个二分图,结点个数分别为n,m,边数为e,求二分图最大匹配数. 解法:匈牙利算法.(以前我总是不记得......)实质上应该有贪心的思想,每次都尽量匹配,找到能和自己匹配的也尽量让它们匹配.若对方已有匹配的对象,就让那个对象尽量调整来使自己这对能凑起来.而要注意,每次问过的对象就不要再问了,也就是不要让它的对象总是换来换去...... 1 #include<cstdio> 2 #include<cstdlib> 3 #include<cstring> 4 #

【二分图】洛谷P1640连续攻击游戏

题目描述 lxhgww最近迷上了一款游戏,在游戏里,他拥有很多的装备,每种装备都有2个属性,这些属性的值用[1,10000]之间的数表示.当他使用某种装备时,他只能使用该装备的某一个属性.并且每种装备最多只能使用一次.游戏进行到最后,lxhgww遇到了终极boss,这个终极boss很奇怪,攻击他的装备所使用的属性值必须从1开始连续递增地攻击,才能对boss产生伤害.也就是说一开始的时候,lxhgww只能使用某个属性值为1的装备攻击boss,然后只能使用某个属性值为2的装备攻击boss,然后只能使

AC自动机(附洛谷P3769模板题)

首先,介绍一下AC自动机(Aho-Corasick automaton),是一种在一个文本串中寻找每一个已给出的模式串的高效算法. 在学习AC自动机之前,你需要先学习Trie树和KMP算法,因为AC自动机正式利用并结合了两者的思想. 说到实际的不同,其实AC自动机只是在Trie树上引入了一个类似KMP中next数组的东西叫做Fail指针. 对于每一个节点,Fail指针指向该节点所代表的字符串中,次长的.在Trie树中存在的后缀(因为最长的在Trie树种存在的后缀就是其本身)所代表的节点. 举例:

洛谷P3375 [模板]KMP字符串匹配

To 洛谷.3375 KMP字符串匹配 题目描述 如题,给出两个字符串s1和s2,其中s2为s1的子串,求出s2在s1中所有出现的位置. 为了减少骗分的情况,接下来还要输出子串的前缀数组next.如果你不知道这是什么意思也不要问,去百度搜[kmp算法]学习一下就知道了. 输入输出格式 输入格式: 第一行为一个字符串,即为s1(仅包含大写字母) 第二行为一个字符串,即为s2(仅包含大写字母) 输出格式: 若干行,每行包含一个整数,表示s2在s1中出现的位置 接下来1行,包括length(s2)个整

【C++】最近公共祖先LCA(Tarjan离线算法)&amp;&amp; 洛谷P3379LCA模板

1.前言 首先我们介绍的算法是LCA问题中的离线算法-Tarjan算法,该算法采用DFS+并查集,再看此算法之前首先你得知道并查集(尽管我相信你如果知道这个的话肯定是知道并查集的),Tarjan算法的优点在于相对稳定,时间复杂度也比较居中,也很容易理解(个人认为). 2.思想 下面详细介绍一下Tarjan算法的思想: 1.任选一个点为根节点,从根节点开始. 2.遍历该点u所有子节点v,并标记这些子节点v已被访问过. 3.若是v还有子节点,返回2,否则下一步. 4.合并v到u上. 5.寻找与当前点

洛谷.3803.[模板]多项式乘法(FFT)

题目链接:洛谷.LOJ. FFT相关:快速傅里叶变换(FFT)详解.FFT总结.从多项式乘法到快速傅里叶变换. #include <cmath> #include <cctype> #include <cstdio> #include <algorithm> #define gc() getchar() const int N=1e6+5; const double PI=acos(-1); int n,m; struct Complex { double

洛谷.1919.[模板]A乘B Problem升级版(FFT)

题目链接:洛谷.BZOJ2179 //将乘数拆成 a0*10^n + a1*10^(n-1) + ... + a_n-1的形式 //可以发现多项式乘法就模拟了竖式乘法 所以用FFT即可 注意处理进位 //n位*n位最多就只有2n位了 //论putchar的速度..还是快的 #include <cmath> #include <cstdio> #include <cctype> #include <algorithm> #define gc() getchar

洛谷—— P3386 【模板】二分图匹配

https://www.luogu.org/problem/show?pid=3386 题目背景 二分图 题目描述 给定一个二分图,结点个数分别为n,m,边数为e,求二分图最大匹配数 输入输出格式 输入格式: 第一行,n,m,e 第二至e+1行,每行两个正整数u,v,表示u,v有一条连边 输出格式: 共一行,二分图最大匹配 输入输出样例 输入样例#1: 1 1 1 1 1 输出样例#1: 1 说明 n,m<=1000,1<=u<=n,1<=v<=m 因为数据有坑,可能会遇到v