Crime
题意:给出n个点m条边,每条边有且只能选一个点,问最少选多少个点
.
.
题解:经典的黑白染色,dfs一次就可以了
#include <iostream>
#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;
const int maxn = 101000;
const int maxm = 100100;
int a[2*maxm], nextt[2*maxm], last[maxn], n, m, tot, t, sum;
int f[maxn];
bool flag;
int min(int x, int y) {
if (x<y) return x;
return y;
}
void insert(int x, int y) {
tot++;
a[tot] = y;
nextt[tot] = last[x];
last[x] = tot;
}
void dfs(int x) {
sum++;
if (f[x] == 1) t++;
int k = last[x];
while (k != 0) {
if (f[a[k]] == 0) {
f[a[k]] = -f[x];
dfs(a[k]);
} else if (f[a[k]] == f[x]) {
flag = false;
return;
}
if (!flag) return;
k = nextt[k];
}
}
int main() {
while (scanf("%d %d", &n, &m) != EOF) {
memset(last, 0, sizeof(last));
memset(a, 0, sizeof(a));
memset(nextt, 0, sizeof(nextt));
memset(f, 0, sizeof(f));
tot = 0;
flag = true;
int x, y, ans = 0;
for (int i = 1; i <= m; i++) {
cin >> x >> y;
insert(x, y);
insert(y, x);
}
for (int i = 1; i <= n; i++) if (f[i] == 0) {
sum = 0;
t = 0;
f[i] = 1;
dfs(i);
ans += min(sum-t, t);
}
if (!flag) {
cout << "Impossible" << endl;
} else
cout << ans << endl;
}
}