一、二分图匹配
给出一张二分图,请求出最大匹配数量
匈牙利算法:
让左边的与右边的
#include <bits/stdc++.h> #define maxn 1005 #define icn cin #define itn int using namespace std; //左边的每个人都尝试去和右边的人匹配 bool z[maxn][maxn];//z[i][j] 代表左边第i个点和右边第j个点能不能匹配 int dist[maxn]; int n,m; bool vis[maxn]; //vis[i] 代表右边第i个点在这一轮中有没有被请求匹配 //左边有n 个点 右边有m个点 int k;//边数 long long ans = 0; int reault[maxn];//result[i] 代表右边第i个点和左边第result[i]个点匹配 bool dfs(int i){//让左边第i个点尝试 for(int j = 1; j <= m; j++)//让左边额第i个点和右边的第j个点尝试匹配 if(z[i][j] && !vis[j]){ vis[j] = true;//有点匹配 if(!result[j] || dfs(result[j])){ result[j] = i; return true; } } return false; } int main(){ ios::sync_with_stdio(false); cin >> n >> m; for(int i = 1; i <= k; i++){ int p1,p2; cin >> p1 >> p2; z[p1][p2] = true; } for(int i = 1; i <= n; i++){ memset(vis,false,sizeof(vis)); if(dfs(i)) ans ++; } cout << ans << '\n'; return 0; //O(n^3) }
优化:
#include<bits/stdc++.h>
#define ll long long
#define itn int
using namespace std;
const int maxn=1005;
int n,m,k;
int ans;
vector<int> z[maxn];
//z[i][j]代表左边第i个点第j个条边连向谁
//n代表左边有n个点
//m代表右边有m个点
bool vis[maxn];
//vis[i]代表右边第i个点在这一轮中有没有被请求匹配
int result[maxn];
//result[i] 代表右边第i个点和左边第result[i]个点匹配
void add_edge(int p1,int p2)
{
z[p1].push_back(p2);
}
inline bool dfs(int i)
{
//让左边第i个点尝试匹配
//返回是否匹配成功
for(int k=0;k<z[i].size();k++)
{
//让左边第i个点和右边第j个点匹配
int j=z[i][k];
if(!vis[j])
{
vis[j]=true;
if(!result[j]||dfs(result[j]))
{
//右边这个点j没有和任何点匹配
result[j]=i;
return true;
}
}
}
return false;
//枚举所有点都不可行
}
int main(){
cin>>n>>m>>k;
for(int i=1;i<=k;i++)
{
int p1,p2;
cin>>p1>>p2;
add_edge(p1,p2);
}
for(int i=1;i<=n;i++)
{
memset(vis,false,sizeof(vis));
if(dfs(i)) ans++;//左边第i个点匹配成功,增加答案数量
}
cout<<ans;
return 0;
}
标签:p2,匹配,个点,int,左边,fds,maxn From: https://www.cnblogs.com/wan169961/p/17549952.html