HDU 5727 (二分图匹配)

题目链接:点击这里

题意:n个阴珠子n个阳珠子间隔串成一串项链,每一组信息u,v表示u号阳珠子放在v号阴珠子旁边会褪色。求出最少褪色阳珠子的个数。

直接STL的全排列枚举阴珠子的排列, 然后对于一种排列, 给每一个位置对应的不会褪色的阳珠子建边, 跑出的最大匹配就是最多的不褪色阳珠子个数。

#include 
#include 
#include 
#include 
#include 
#include 
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;//阳珠子u在阴珠子v旁会变暗
        }
        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;
}

你可能感兴趣的:(二分图)