OJ 1899. Kaze
题目描述
给定一个 n个点 m条无向边的二分图,请输出一个图上的最大独立集。
输入图保证是一个二分图:存在
f
:
V
↦
{
0
,
1
}
f : V\mapsto \{0, 1\}
f:V↦{0,1},使得
∀
(
u
,
v
)
∈
E
,
f
(
u
)
≠
f
(
v
)
\forall (u, v) \in E, f(u) \neq f(v)
∀(u,v)∈E,f(u)=f(v)。
一个点集 S是独立集,当且仅当
∀
(
u
,
v
)
∈
E
,
u
∉
S
∨
v
∉
S
\forall (u, v) \in E, u \notin S \lor v \notin S
∀(u,v)∈E,u∈/S∨v∈/S为真。
最大独立集指独立集中大小最大的。
Input
第一行输入n,m
接下来 m 行,第 i 行为用空格隔开的整数
u
i
u_i
ui,
v
i
v_i
vi,表示一条
u
i
u_i
ui到
v
i
v_i
vi的无向边。
1
≤
n
≤
1000
1≤n≤1000
1≤n≤1000,
0
≤
m
≤
⌊
n
/
2
⌋
⋅
⌈
n
/
2
⌉
0≤m≤⌊n/2⌋⋅⌈n/2⌉
0≤m≤⌊n/2⌋⋅⌈n/2⌉.保证没有重边与自环。
Output
第一行输出
k
k
k
(
1
≤
k
≤
n
)
(1 \leq k \leq n)
(1≤k≤n),表示最大独立集的大小。
接下来一行输出 k个空格隔开的不重复正整数,表示一个最大独立集里点的标号。
如果有多种方案,输出任意一种。
Sample Input
Sample 1
3 2
1 2
2 3
Sample 2
4 4
1 3
1 4
2 3
2 4
Sample Output
Sample 1
2
1 3
Sample 2
2
1 2
Solution
最大独立集=顶点数-最大匹配数
先用匈牙利算法求最大匹配,然后合理取点求最大独立集。
匈牙利算法详解:https://blog.csdn.net/qq_49688477/article/details/119777445
Code
#include<iostream>
#include<vector>
#include<queue>
using namespace std;
int n,m;
vector<bool> vis;
vector<vector<bool>> g;//邻接矩阵
vector<int> part;
vector<int> l;
vector<int> r;
vector<bool> ans;
bool hungarian(int i){
for(int j=1;j<n+1;j++){
if(g[i][j]&&!vis[j]){
vis[j]=true;
if(l[j]==0||hungarian(l[j])){
l[j]=i;
r[i]=j;
return true;
}
}
}
return false;
}
int main()
{
cin>>n>>m;
part.assign(n+1,0);
l.assign(n+1,0);
r.assign(n+1,0);
ans.assign(n+1,false);
g.assign(n+1,vector<bool>(n+1));
int u, v;
for(int i=0;i<m;i++){
cin>>u>>v;
g[u][v]=true;
g[v][u]=true;
}
for(int i=1;i<n+1;i++){
if(part[i]==0){
queue<int> q;
part[i]=1;//二分图左边的点
q.push(i);
while(!q.empty()){
int cur=q.front();
q.pop();
for(int j=1;j<n+1;j++){
if(g[cur][j]){
if(part[j]==0){
part[j]=part[cur]*(-1);
q.push(j);
}
}
}
}
}
}
for(int i=1;i<n+1;i++){
//cout<<part[i]<<endl;
if(part[i]!=1){
continue;
}
vis.assign(n+1,false);
if(!hungarian(i)){
ans[i]=true;
}
}
for(int i=1;i<n+1;i++){
if(part[i]==1){
ans[i]=true;
}
}
for(int i=1;i<n+1;i++){
//cout<< i<<"i "<<l[i]<<" "<<r[i]<<endl;
if(part[i]==-1&&l[i]==0){
vis.assign(n+1,false);
vis[i]=true;
queue<int> ql;
queue<int> qr;
qr.push(i);
ans[i]=true;
while(!qr.empty()){
int vexr=qr.front();
qr.pop();
for(int j=1;j<n+1;j++){
if(g[vexr][j]&&!vis[j]){
ql.push(j);
ans[j]=false;
}
}
while(!ql.empty()){
int vexl=ql.front();
ql.pop();
if(r[vexl]!=0 && !vis[r[vexl]]){
qr.push(r[vexl]);
vis[r[vexl]]=true;
ans[r[vexl]]=true;
}
}
}
}
}
int count=0;
for(int i=1;i<n+1;i++){
if(ans[i]){
count++;
}
}
cout<<count<<endl;
for(int i=1;i<n+1;i++){
if(ans[i]){
cout<<i<<" ";
}
}
return 0;
}