0
点赞
收藏
分享

微信扫一扫

hdu2063过山车 匈牙利算法&最大流求解二分图

浮游图灵 2022-06-29 阅读 44

​​传送门​​​ 思路:求男孩和女孩的配对个数。裸的匈牙利算法,用dinic建图直接求最大流也行。
匈牙利算法
大佬博客

#include<iostream>
#include<cstring>
#include<algorithm>
#include<cstdio>
#include<cstdlib>
#include<queue>
#include<cmath>
#include<cctype>
#include<stack>
#include<map>
#include<string>
#include<cstdlib>
#define ll long long
#define mem(a,b) memset(a,b,sizeof(a))
#define maxn 1010
#define InF 0x3f3f3f3f
using namespace std;
int G[maxn][maxn], used[maxn], vis[maxn], m;
bool Find(int u) {
for(int i = 1 ; i <= m ; i++) {
if(!vis[i] && G[u][i]) {
///vis[i]表示i男生还没有被别的女生选走
vis[i] = 1;
if(!used[i] || Find(used[i])) {
///如果女生used[i]没有选男生i作伴或者女生used[i]选了男生i,她放弃男生i并且另外找到了自己的伴
///当前还可以挪出来位置
used[i] = u;///就让男生i与女生u作伴
return true;
}
}
}
return false;
}///该函数判断女生能不能找到伴
int main() {
int k, n, i, a, b, ans;
while(cin >> k >> n >> m) { ///n 女生 m 男生
ans = 0;
mem(G, 0);
while(k--) {
cin >> a >> b;
G[a][b] = 1;///G[a][b]表示女生a愿意与男生b作伴
}///used[i]表示i男生与used[i]女生作伴
mem(used, 0);
for(i = 1 ; i <= n ; i++) {
mem(vis, 0);
if(Find(i))
ans++;
}
cout << ans << endl;
}
return 0;
}

dinic最大流建图

#include<cstdio>
#include<cstring>
#include<cmath>
#include<cstdlib>
#include<ctime>
#include<climits>
#include<algorithm>
#include<complex>
#include<iostream>
#include<map>
#include<queue>
#include<vector>
#define mem(a,b) memset(a,b,sizeof a)
#define INF 0x3f3f3f3f
#define inf 0x3f3f3f3f3f3f3f3f
#define ll long long
#define maxn 100005
using namespace std;
int n, m; //点数、边数
int s, t; //原点、汇点
struct node {
int v, next;
int cap;
} mp[maxn * 10];
int pre[maxn], dis[maxn], cur[maxn]; //cur为当前弧优化,dis存储分层图中每个点的层数(即到原点的最短距离),pre建邻接表
int cnt, edge_num = 1;
int vis[maxn], Dis[maxn];
int head1[maxn], head[maxn];
void add(int u, int v, int w) { //加边
mp[++edge_num].v = v;
mp[edge_num].cap = w;
mp[edge_num].next = pre[u];
pre[u] = edge_num;
}
bool bfs(int s) { //建分层图
mem(dis, -1);
queue<int>q;
while(!q.empty())
q.pop();
q.push(s);
dis[s] = 0;
int u, v;
while(!q.empty()) {
u = q.front();
q.pop();
for(int i = pre[u]; i != -1; i = mp[i].next) {
v = mp[i].v;
if(dis[v] == -1 && mp[i].cap > 0) {
dis[v] = dis[u] + 1;
q.push(v);
if(v == t)
return 1;
}
}
}
return dis[t] != -1;
}
int dfs(int u, int cap) { //寻找增广路
if(u == t || cap == 0)
return cap;
int res = 0, f;
for(int &i = cur[u]; i != -1; i = mp[i].next) {
int v = mp[i].v;
if(dis[v] == dis[u] + 1 && mp[i].cap > 0) {
f = dfs(v, min(cap, mp[i].cap));
mp[i].cap -= f;
mp[i ^ 1].cap += f;
res += f;
cap -= f;
if(cap == 0) break;
}
}
if(cap > 0)
dis[u] = -1;
return res;
}
int dinic( ) {
int ans = 0;
while(bfs(s)) {
memcpy(cur, pre, sizeof pre);
ans += dfs(s, inf);
}
return ans;
}
int main() {
int k;
while(cin >> k >> m >> n ) {
mem(pre, -1);
mem(mp,0);
edge_num = 1;
s = n + m + 1, t = s + 1;
for(int i = 1; i <= m; i++) {
add(s, i, 1);
add(i, s, 0);
}
for(int i = 1 + m; i <= n + m; i++) {
add(i, t, 1);
add(t, i, 0);
}
for(int i = 1; i <= k; i++) {
int u, v;
cin >> u >> v;
add(u, v + m, 1);
add(v + m, u, 0);
}
cout << dinic() << endl;
}
return 0;
}


举报

相关推荐

0 条评论