您的位置:首页 > 其它

过山车 hdu2063 匹配、匈牙利算法起步&&最大流

2018-02-12 11:59 429 查看
现在开始接触这学期学得最差的一部分——匹配算法(或者说直接没学过吧。。期末oj死得很惨),虽说我感觉死得最惨的问求试卷上并不是这种题。
这题是道很简单的二分匹配,直接应用匈牙利算法求解即可。#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <vector>
#include <string.h>
#include <algorithm>
using namespace std;
#define MAXN 503
int K, N, M;
vector<int > leftGraph[MAXN];
bool rigtVisited[MAXN];
int boysPair[MAXN];
void init()
{
for (int i = 0; i < N; i++)
leftGraph[i].clear();
for (int i = 0; i < K; i++) {
int ai,bi;
scanf("%d %d", &ai, &bi);
leftGraph[ai - 1].push_back(bi - 1);
}
}
bool find(int x)
{
for (int i = 0; i < leftGraph[x].size(); i++) {
int boy = leftGraph[x][i];
if (rigtVisited[boy] == false) {
rigtVisited[boy] = true;
if (boysPair[boy] < 0 || find(boysPair[boy])) {
boysPair[boy] = x;
return true;
}
}
}
return false;
}
void solve()
{
memset(boysPair, 0xff, sizeof(boysPair));
int sum = 0;
for (int i = 0; i < M; i++) {
memset(rigtVisited, 0, sizeof(rigtVisited));
if (find(i))
sum++;
}
printf("%d\n", sum);
}
int main()
{
while (scanf("%d", &K) != EOF&&K) {
scanf("%d %d", &M, &N);
init();
//show();
solve();
}
return 0;
}当然也可以用算法导论第二十六章中提到的网络流方法来做,即多设置一个源点和一个汇点,并将边权都设为1来解(其中用到的Dinic算法的最大流模板,是谁的我忘了,侵删(可能是来自百度百科的吧2333))#include <stdio.h>
#include <algorithm>
#include <iostream>
using namespace std;
#include <queue>
#define MAXN 26000
#define MAXE 10000
#define INF 0x3f3f3f3f

typedef int iter;
class matchGraph
{
private:
int s, t;
int cnt;
int Head[MAXN];//the number for the last edge of a certain vertex
int Next[MAXE];//pointing to the former edge of a certain edge?
int V[MAXE];//the vertex each edge points to
int W[MAXE];
int Depth[MAXN];
void _add(int u, int v, int w)
{
Next[cnt] = Head[u];//this mimics a list?
V[cnt] = v;
W[cnt] = w;
Head[u] = cnt;
cnt++;
}
public:
int order;
void init(int oorder, int ss, int tt)
{//s is the souce and t is the sink
this->order = oorder;
s = ss;
t = tt;
cnt = 0;
//printf("S:%d\tT:%d\n", s, t);
memset(Head, -1, sizeof(Head));
memset(Next, -1, sizeof(Next));
}
void addEdge(int u, int v, int w)
{
//printf("added %d->%d with %d\n", u, v, w);
_add(u, v, w);
_add(v, u, 0);
}
int dfs(int u, int dist)
{//u being the present node and dist being the present flow
if (u == t)
return dist;
int i, di;
for (i = Head[u]; i != -1; i = Next[i]) {
if ((Depth[V[i]] == Depth[u] + 1) && W[i] != 0) {
di = dfs(V[i], min(dist, W[i]));
if (di > 0) {
W[i] -= di;
W[i ^ 1] += di;
return di;
}
}
}
return 0;
}
bool bfs()
{
queue<int > Q;
int u;
while (!Q.empty())
Q.pop();
memset(Depth, 0, sizeof(Depth));
Depth[s] = 1;
Q.push(s);
while (!Q.empty()) {
u = Q.front();
Q.pop();
for (int i = Head[u]; i != -1; i = Next[i]) {
if ((W[i] > 0) && Depth[V[i]] == 0) {
Depth[V[i]] = Depth[u] + 1;
Q.push(V[i]);
}
}
}
/* printf("Depths now:\n");
for (int i = 0; i < order; i++)
printf("%d%s", Depth[i], i == order - 1 ? "\n" : "\t");
*/
return Depth[t] > 0 ? true : false;
}
int Dinic()
{
int Ans = 0, d;
while (bfs()) {
while (d = dfs(s, INF)) {
Ans += d;
//printf("Ans:%d\n", Ans);
}
}
return Ans;
}
};

int main()
{
matchGraph mG;
int k, m, n;
while (scanf("%d", &k) != EOF&&k) {
scanf("%d %d", &m, &n);
mG.init(m + n + 2, 0, m + n + 1);
int u, v;
for (int i = 0; i < k; i++) {
scanf("%d %d", &u, &v);
mG.addEdge(u, m+v, 1);
}
for (int i = 0; i < m; i++)
mG.addEdge(0, i + 1, 1);
for (int i = 0; i < n; i++)
mG.addEdge(m + 1 + i, m + n + 1, 1);
printf("%d\n", mG.Dinic());
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  matching