#pragma warning (disable : 4996)
#include<cstdio>
#include<queue>
#include<vector>
#include<cstring>
using namespace std;
const int maxn = 2e2 + 10;
struct node {
int to, nxt;
}edge[maxn * 100];
int head[maxn], col[maxn], match[maxn], vis[maxn];
int ecnt = 0;
void addedge(int u, int v) {//邻接表比vector快
edge[ecnt].to = v;
edge[ecnt].nxt = head[u];
head[u] = ecnt++;
}
bool bfs(int s) {//染色 判断二分图
memset(col, 0, sizeof col);
queue<int> q;
col[s] = 1;
q.push(s);
while (!q.empty()) {
s = q.front();
q.pop();
for (int i = head[s]; i + 1; i = edge[i].nxt) {
if (col[edge[i].to] == 0)
col[edge[i].to] = -col[s], q.push(edge[i].to);
if (col[edge[i].to] == col[s])
return false;
}
}
return true;
}
bool dfs(int s) {//匈牙利算法
for (int i = head[s]; i + 1; i = edge[i].nxt) {
if (vis[edge[i].to] == false) {
vis[edge[i].to] = true;
if (match[edge[i].to] == 0 || dfs(match[edge[i].to])) {
match[edge[i].to] = s;
//match[s] = edge[i].to;
return true;
}
}
}
return false;
}
int main() {
int n, m;
while (scanf("%d%d", &n, &m) != EOF) {
memset(match, 0, sizeof(match));
memset(head, -1, sizeof head);//必须是-1, 0 会干扰答案
ecnt = 0;
for (int i = 1; i <= m; i++) {
int a, b;
scanf("%d%d", &a, &b);
addedge(a, b);
//addedge(b, a); //一样的,建双向边就要 ans /= 2
}
if (!bfs(1)) {
puts("No");
}
else {
int sum = 0;
for (int i = 1; i <= n; i++) {
memset(vis, false, sizeof(vis));
if (dfs(i)) {
sum++;
}
}
printf("%d\n", sum);
}
}
return 0;
}
#pragma warning (disable : 4996)
#include<cstdio>
#include<queue>
#include<vector>
#include<cstring>
using namespace std;
const int maxn =2e2+10;
int col[maxn], match[maxn], vis[maxn];
vector<int> v[maxn];//邻接矩阵存图
bool bfs(int s) {//染色 判断二分图
memset(col, 0, sizeof col);
queue<int> q;
col[s] = 1;
q.push(s);
while (!q.empty()) {
s = q.front();
q.pop();
int len = v[s].size();
for (int i = 0; i < len; ++i) {
if (col[v[s][i]] == 0)
col[v[s][i]] = -col[s], q.push(v[s][i]);
if (col[v[s][i]] == col[s])
return false;
}
}
return true;
}
bool dfs(int s) {
int len = v[s].size();
for (int i = 0; i < len; ++i) {
if (vis[v[s][i]] == false) {
vis[v[s][i]] = true;
if (match[v[s][i]] == 0 || dfs(match[v[s][i]])) {
match[v[s][i]] = s;
//match[s] = v[s][i];//建双向边的时候就不要这个了//一般好像也不需要,似乎是多余的东西
return true;
}
}
}
return false;
}
int main() {
int n, m;
while (scanf("%d%d", &n, &m) != EOF) {
memset(match, 0, sizeof(match));
for (int i = 0; i <= n; ++i) {
v[i].clear();
}
for (int i = 1; i <= m; i++) {
int a, b;
scanf("%d%d", &a, &b);
v[a].push_back(b);
v[b].push_back(a);//建无向图 答案就要 ans/=2
}
if (!bfs(1)) {
puts("No");
}
else {
int sum = 0;
for (int i = 1; i <= n; i++) {
memset(vis, false, sizeof(vis));
if (dfs(i)) {
sum++;
}
}
printf("%d\n", sum/2);
}
}
return 0;
}