2013-team4/code/hungary
从 Trac 迁移的文章
这是从旧校内 Wiki 迁移的文章,可能存在一些样式问题,您可以向 memset0 反馈。
原文章内容如下:
{{{
匈牙利算法
不区分两侧的点,全部点个数为 n,编号从 1 开始
}}}
{{{
const int N = 2005;
struct Hungary{
int match[N];
bool vis[N];
vector<int> G[N];
int n, col[N];
// 全图共 n 个顶点
void init(int n){
this->n = n;
for(int i = 1; i <= n; i++) G[i].clear();
}
// 添加边
void add_edge(int a, int b){
G[a].push_back(b);
G[b].push_back(a);
}
// 以下两个函数求最大匹配
bool dfs(int x){
vis[x] = true;
for(int i = 0; i < G[x].size(); i++){
int y = G[x][i], z = match[y];
vis[y] = true;
if(z < 0 || !vis[z] && dfs(z)){
match[x] = y; match[y] = x;
return true;
}
}
return false;
}
// 返回最大匹配,匹配的顶点在 match[i] 中,没有为 -1
int max_matching(){
int ret = 0;
memset(match, -1, sizeof(match));
for(int i = 1; i <= n; i++){
if(match[i] < 0){
memset(vis, 0, sizeof(vis));
if(dfs(i)) ret++;
}
}
return ret;
}
// 以下两个函数求解最大独立集和最小顶点覆盖
// 用 0 或 1 染色,区分开两个集合
void color(){
for(int i = 1; i <= n; i++){
if(i <= r) col[i] = 0;
else col[i] = 1;
}
}
// 构造最小顶点覆盖或最大独立集,返回数组长度
int solve(int *arr){
max_matching();
color();
memset(vis, 0, sizeof(vis));
for(int i = 1; i <= n; i++)
if(col[i] == 0 && match[i] == -1)
dfs(i);
int p = 0;
for(int i = 1; i <= n; i++){
if(col[i] == 0 && !vis[i] || col[i] == 1 && vis[i]){
// 最小顶点覆盖
arr[p++] = i;
}
else{
// 最大独立集
//arr[p++] = i;
}
}
return p;
}
};
}}}
匈牙利算法
不区分两侧的点,全部点个数为 n,编号从 1 开始
const int N = 2005;
struct Hungary{
int match[N];
bool vis[N];
vector<int> G[N];
int n, col[N];
// 全图共 n 个顶点
void init(int n){
this->n = n;
for(int i = 1; i <= n; i++) G[i].clear();
}
// 添加边
void add_edge(int a, int b){
G[a].push_back(b);
G[b].push_back(a);
}
// 以下两个函数求最大匹配
bool dfs(int x){
vis[x] = true;
for(int i = 0; i < G[x].size(); i++){
int y = G[x][i], z = match[y];
vis[y] = true;
if(z < 0 || !vis[z] && dfs(z)){
match[x] = y; match[y] = x;
return true;
}
}
return false;
}
// 返回最大匹配,匹配的顶点在 match[i] 中,没有为 -1
int max_matching(){
int ret = 0;
memset(match, -1, sizeof(match));
for(int i = 1; i <= n; i++){
if(match[i] < 0){
memset(vis, 0, sizeof(vis));
if(dfs(i)) ret++;
}
}
return ret;
}
// 以下两个函数求解最大独立集和最小顶点覆盖
// 用 0 或 1 染色,区分开两个集合
void color(){
for(int i = 1; i <= n; i++){
if(i <= r) col[i] = 0;
else col[i] = 1;
}
}
// 构造最小顶点覆盖或最大独立集,返回数组长度
int solve(int *arr){
max_matching();
color();
memset(vis, 0, sizeof(vis));
for(int i = 1; i <= n; i++)
if(col[i] == 0 && match[i] == -1)
dfs(i);
int p = 0;
for(int i = 1; i <= n; i++){
if(col[i] == 0 && !vis[i] || col[i] == 1 && vis[i]){
// 最小顶点覆盖
arr[p++] = i;
}
else{
// 最大独立集
//arr[p++] = i;
}
}
return p;
}
};