一、二分圖匹配
給出一張二分圖,請求出最大匹配數量
匈牙利算法:
讓左邊的與右邊的
#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;
}
浙公網安備 33010602011771號