您的位置:首页 > 其它

hdu 5727(匈牙利算法)

2016-07-23 18:05 459 查看
这里

因为是环状,固定一个阴石,其他阴石枚举全排列,然后枚举每个阳石放的位置,建二分图(如果阳石放的位置不会引起爆炸,就连边),跑匈牙利求出最大匹配。n - 最大匹配就是 最少的引起爆炸的阳石数量,再取min

#include <bits/stdc++.h>

#pragma comment(linker, "/STACK:102400000,102400000")
using namespace std;

#define LL long long
#define pii pair<int,int>
#define MP make_pair
#define ls i << 1
#define rs ls | 1
#define md (ll + rr >> 1)
#define lson ll, md, ls
#define rson md + 1, rr, rs
#define Pi acos(-1.0)
#define mod 1000000007
#define eps 1e-10
#define inf 0x3f3f3f3f
#define N 10
#define M 800020

bool g

, vis
;
int fst
, vv[M], nxt[M], e;
int n, m, p
, a
, match
;
void init(){
memset(fst, -1, sizeof fst); e = 0;
}
void add(int u, int v){
vv[e] = v, nxt[e] = fst[u], fst[u] = e++;
}
bool hungry(int u){
for(int i = fst[u]; ~i; i = nxt[i]){
int v = vv[i];
if(!vis[v]){
vis[v] = 1;
if(match[v] == 0 || hungry(match[v])){
match[v] = u;
return 1;
}
}
}
return 0;
}
int calc(){
init();
p[1] = 1;
for(int i = 2; i <= n; ++i) p[i] = a[i-1] + 1;
for(int i = 1; i <= n; ++i){
for(int j = 1; j <= n; ++j){
int l = p[j], r = p[j+1];
if(j == n) r = p[1];
if(!g[i][l] && !g[i][r]){
add(i, j);
}
}
}
int ret = 0;
memset(match, 0, sizeof match);
for(int i = 1; i <= n; ++i){
if(!match[i]){
memset(vis, 0, sizeof vis);
if(hungry(i))
ret++;
}
}
return n - ret;
}
int main(){
while(scanf("%d%d", &n, &m) != EOF){
memset(g, 0, sizeof g);
for(int i = 1; i <= m; ++i){
int u, v;
scanf("%d%d", &u, &v);
g[u][v] = 1;
}
if(n == 0 || m == 0){
puts("0"); continue;
}
if(n == 1){
printf("%d\n", m); continue;
}
for(int i = 1; i < n; ++i) a[i] = i;
int ans = n;
do{
ans = min(ans, calc());
}while(next_permutation(a + 1, a + n));
printf("%d\n", ans);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: