HDU 5727(二分图匹配 + STL全排列)

STL 中 next_permutation 用法: 

int a[5] = {1,2,3,4,5};
do{
    for(int i = 0;i < 5;++i)
        printf("%d   ",a[i]);
    puts("");
}while(next_permutation(a,a+5));

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

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

代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;
struct Edge{
    int to,next;
}edge[505];
int match[11],head[11];
int to[11];
bool mp[11][11],vis[11];
bool dfs(int u){
    for(int i = head[u];i != -1;i = edge[i].next){
        int v = edge[i].to;
        if(!vis[v]){
            vis[v] = 1;
            if(!match[v] || dfs(match[v])){
                match[v] = u;
                to[u] = v;
                return true;
            }
        }
    }
    return false;
}
int a[14];
int main()
{
    int n,m;
    while(~scanf("%d%d",&n,&m)){
        if(n == 0 || m == 0){
            puts("0");
            continue;
        }
        for(int i = 1;i <= n;++i) a[i] = i;
        memset(mp,0,sizeof(mp));
        int u,v;
        for(int i = 1;i <= m;++i){
            scanf("%d%d",&u,&v);
            mp[u][v] = 1;
        }
        int ans = n;
        do{
            memset(head,-1,sizeof(head));
            memset(match,0,sizeof(match));
            memset(to,0,sizeof(to));
            a[0] = a[n];
            int cnt = 0;
            for(int i = 0;i < n;++i){
                for(int j = 1;j <= n;++j){
                    if(!mp[j][a[i]] && !mp[j][a[i+1]]){
                        edge[cnt].to = i+1,edge[cnt].next = head[j],head[j] = cnt++;
                    }
                }
            }
            int temp = 0;
            for(int i = 1;i <= n;++i){
                memset(vis,0,sizeof(vis));
                if(!to[i]) temp += dfs(i);
            }
            ans = min(ans,n - temp);
            if(!ans) break;
        }while(next_permutation(a+2,a+n+1));
        printf("%d\n",ans);
    }
    return 0;
}

TLE原因:

0.出题人是SB

1. ans = 0时可以直接退出

2.由于是圆排列,所以全排列可以直接从2位置开始做

猜你喜欢

转载自blog.csdn.net/offbyonebug/article/details/80031894
今日推荐