题意:
简化题意就是判断一个图是否是二分图,如果是求出最大匹配。
思路:
模板题,但是还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;
}