过山车 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;
}
这题是道很简单的二分匹配,直接应用匈牙利算法求解即可。#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;
}
相关文章推荐
- 【HDU2063】过山车(二分图最大匹配,匈牙利算法)
- hdu2063 过山车--最大匹配数 & 匈牙利
- hdu2063 过山车 二分图/最大匹配(匈牙利算法)
- hdu2063 过山车 二分图最大匹配 匈牙利算法
- 最大二分匹配 匈牙利算法模板&&POJ 1469 COURSES
- nyoj 239 月老的难题 【二分图&&最大匹配&&匈牙利算法】
- HDU2063-过山车(二分匹配 +匈牙利算法)
- 二分图最大匹配-匈牙利算法-HDU2063-HDU1068-HDU1150-HDU2119
- 【二分图最大匹配】【匈牙利算法】poj1469 COURSES && poj2446 Chessboard
- 【杭电oj】2063 - 过山车(二分图最大匹配,匈牙利算法)
- hdu2063(最大匹配+匈牙利算法)
- hdu2063 最大匹配数(匈牙利算法)
- hdu 2603 过山车 最大匹配,匈牙利算法模板(易理解)
- 利用匈牙利算法&Hopcroft-Karp算法解决二分图中的最大二分匹配问题
- HDU 2063 过山车 【匈牙利算法,二分图最大匹配】
- 利用匈牙利算法&Hopcroft-Karp算法解决二分图中的最大二分匹配问题 例poj 1469 COURSES
- 杭电oj--2063 - 过山车【二分图最大匹配,匈牙利算法】
- HDU 2063 过山车 (最大匹配,匈牙利算法)
- HDOJ 2063 过山车 ——二分图最大匹配(以邻接矩阵,邻接表为数据结构的匈牙利算法)
- hdu 2063 过山车 (最大匹配 匈牙利算法模板)