题意:n个阴珠子n个阳珠子间隔串成一串项链,每一组信息u,v表示u号阳珠子放在v号阴珠子旁边会褪色。求出最少褪色阳珠子的个数。
直接STL的全排列枚举阴珠子的排列, 然后对于一种排列, 给每一个位置对应的不会褪色的阳珠子建边, 跑出的最大匹配就是最多的不褪色阳珠子个数。
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <cmath>
#include <map>
using namespace std;
#define maxn 11
#define INF 1111
int a[maxn*2], permutation[maxn];
int n, m;
bool ok[maxn][maxn];
int ans;
struct node {
int v, next;
} edge[maxn*maxn];
int head[maxn], cnt;
void add_edge (int u, int v) {
edge[cnt].v = v, edge[cnt].next = head[u], head[u] = cnt++;
}
int pre[maxn], vis[maxn];
bool dfs (int u) {
for (int i = head[u]; i != -1; i = edge[i].next) {
int v = edge[i].v;
if (!vis[v]) {
vis[v] = 1;
if (pre[v] == -1 || dfs (pre[v])) {
pre[v] = u;
return 1;
}
}
}
return 0;
}
int hungry () {
int ans = 0;
memset (pre, -1, sizeof pre);
for (int i = 1; i <= n; i++) {
memset (vis, 0, sizeof vis);
if (dfs (i))
ans++;
}
return n-ans;
}
void solve () {
memset (head, -1, sizeof head);
cnt = 0;
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= n; j++) {
int next = i, pre = i-1;if (pre == 0) pre = n;
if (!ok[j][a[next]] && !ok[j][a[pre]])
add_edge (j, i);
}
}
ans = min (ans, hungry ());
}
int main () {
while (scanf ("%d%d", &n, &m) == 2) {
memset (ok, 0, sizeof ok);
for (int i = 0; i < m; i++) {
int u, v;
scanf ("%d%d", &u, &v);
ok[u][v] = 1;
}
if (n == 0 || m == 0) {
printf ("0\n");
continue;
}
for (int i = 1; i <= n; i++) a[i] = i;
ans = INF;
do {
solve ();
} while (next_permutation (a+1, a+n));
printf ("%d\n", ans);
}
return 0;
}