PS: 二分图+最大匹配。 先判断是否为二分图同时对图进行染色,如果不是二分图输出No如果是二分图则将图分为左右两边的"标准二分图“,然后求解最大匹配
二分图没做几个题目, 就是凭着自己想着写的,代码不是很简洁。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <vector>
using namespace std;
const int MAX = 210;
vector<int> G[MAX];
int n, m;
int color[MAX]; // 1 or -1
bool dfs(int v, int c) {
color[v] = c;
for(int i = 0; i < (int)G[v].size(); i++) {
int u = G[v][i];
if(color[u] == c) return false;
if(color[u] == 0 && !dfs(u, -c)) return false;
}
return true;
}
bool bipartite() {
for(int i = 1; i <= n; i++) {
if(color[i] == 0) {
if(!dfs(i, 1)) {
return false;
}
}
}
return true;
}
vector<int> g[MAX];
int from[MAX], tot;
int use[MAX];
int Match(int x) {
for(int i = 0; i < (int)g[x].size(); i++) {
int u = g[x][i];
if(!use[u]) {
use[u] = true;
if(from[u]==-1 || Match(from[u])) {
from[u] = x;
return true;
}
}
}
return false;
}
int hungary() {
tot = 0;
memset(from, 255, sizeof(from));
for(int i = 1; i <= n; i++) {
if(color[i]==1) {
memset(use, 0, sizeof(use));
if(Match(i)) {
++tot;
}
}
}
return tot;
}
void build_map() {
for(int i = 1; i <= n; i++) g[i].clear();
for(int i = 1; i <= n; i++) {
if(color[i]==1) {
for(int j = 0; j < (int)G[i].size(); j++) {
int &u = G[i][j];
g[i].push_back(u);
}
}
}
}
int main()
{
while(scanf("%d%d", &n, &m) != EOF) {
memset(color, 0, sizeof(color));
int x, y;
for(int i = 1; i <= 205; i++) G[i].clear();
for(int i = 1; i <= m; i++) {
scanf("%d%d", &x, &y);
G[x].push_back(y);
G[y].push_back(x);
}
bool ok = bipartite();
if(!ok) {
printf("No\n");
continue;
} else {
build_map();
int res = hungary();
printf("%d\n", res);
}
}
return 0;
}