您的位置:首页 > 其它

HDU - 2444 二分图判定 + 最大匹配

2017-01-23 10:05 204 查看

题意:

简化题意就是判断一个图是否是二分图,如果是求出最大匹配。

思路:

模板题,但是还wa了好久,有个地方需要注意,在判断是否是二分图的时候,一定要从每个未染色的节点出发判定,不能只任意选一个节点。
另外一点是我zz了,在转化成二分图之后左边和右边的节点下标都应该从1开始,而不能用原始图的下标。

代码:

#include <bits/stdc++.h>
using namespace std;
const int MAXN = 205;
const int INF = 0x3f3f3f3f;

int color[MAXN];
vector <int> G[MAXN];

bool bipartite(int u) {
for (int i = 0; i < (int)G[u].size(); i++) {
int v = G[u][i];
if (color[v] == color[u]) return false;
if (!color[v]) {
color[v] = 3 - color[u];
if (!bipartite(v)) return false;
}
}
return true;
}

int nx, ny, dis;
bool bg[MAXN][MAXN];
int dx[MAXN], dy[MAXN], cx[MAXN], cy[MAXN], Hash[MAXN];
bool bmask[MAXN];

bool bfs() {
queue <int> que;
dis = INF;
memset(dx, -1, sizeof(dx));
memset(dy, -1, sizeof(dy));
for (int i = 1; i <= nx; i++) if (cx[i] == -1) {
que.push(i); dx[i] = 0;
}
while (!que.empty()) {
int u = que.front(); que.pop();
if (dx[u] > dis) break;
for (int v = 1; v <= ny; v++) {
if (bg[u][v] && dy[v] == -1) {
dy[v] = dx[u] + 1;
if (cy[v] == -1) dis = dy[v];
else {
dx[cy[v]] = dy[v] + 1;
que.push(cy[v]);
}
}

}
}
return dis != INF;
}

int Hungarian(int u) {
for (int v = 1; v <= ny; v++) {
if (!bmask[v] && bg[u][v] && dy[v] == dx[u] + 1) {
bmask[v] = 1;
if (cy[v] != -1 && dy[v] == dis) continue;
if (cy[v] == -1 || Hungarian(cy[v])) {
cy[v] = u; cx[u] = v;
return 1;
}
}
}
return 0;
}

int MaxMatch() {
int res = 0;
memset(cx, -1, sizeof(cx));
memset(cy, -1, sizeof(cy));
while (bfs()) {
memset(bmask, 0, sizeof(bmask));
for (int i = 1; i <= nx; i++)
if (cx[i] == -1) res += Hungarian(i);
}
return res;
}

int main() {
int n, m;
while (scanf("%d%d", &n, &m) == 2) {
for (int i = 1; i <= n; i++) G[i].clear();
for (int i = 1; i <= m; i++) {
int x, y;
scanf("%d%d", &x, &y);
G[x].push_back(y);
G[y].push_back(x);
}
bool flag = true;
memset(color, 0, sizeof(color));
for (int i = 1; i <= n; i++) {
if (color[i]) continue;
color[i] = 1;
if (!bipartite(i)) {
flag = false;
break;
}
}
if (!flag) {
puts("No");
continue;
}
nx = ny = 0;
memset(bg, false, sizeof(bg));
for (int i = 1; i <= n; i++) {
if (color[i] == 1) Hash[i] = ++nx;
else Hash[i] = ++ny;
}
for (int i = 1; i <= n; i++) {
for (int j = 0; j < (int)G[i].size(); j++) {
int v = G[i][j];
if (color[i] == 1) bg[Hash[i]][Hash[v]] = true;
else bg[Hash[v]][Hash[i]] = true;
}
}
printf("%d\n", MaxMatch());
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  acm 二分图 图论