二分图中
最小覆盖数=最大匹配数
证明:http://blog.csdn.net/qq_30802053/article/details/77482209
用匈牙利算法求最大匹配数;
下面再求输出方案:
上面的连接讲了求最小覆盖数的选择点,选择Right[i]==-1(就是找非匹配边)的点进行match(i),然后选S集合中未标记的和T集合中标记了的就是输出方案。
代码:
#include<iostream>
#include<cstring>
using namespace std;
const int maxn=101;
int S[maxn],T[maxn],Left[maxn],Right[maxn];
int link[maxn][maxn],n,m;
bool match(int i){
S[i]=1;
for(int j=1;j<=m;j++)if(!T[j]&&link[i][j]){
T[j]=true;
if(!Left[j]||match(Left[j])){
Left[j]=i;
Right[i]=j;
return true;
}
}
return false ;
}
void Maxmatch(){
memset(Left,0,sizeof(Left));
memset(Right,-1,sizeof(Right));
int ans=0;
for(int i=1;i<=n;i++){
memset(T,0,sizeof(T));
memset(S,0,sizeof(S));
if(match(i))ans++;
}
cout<<ans<<" ";
memset(T,0,sizeof(T));
memset(S,0,sizeof(S));
for(int i=1;i<=n;i++){
if(Right[i]==-1){
match(i);//cout<<i<<" ";
}
}
for(int u=1;u<=n;u++)if(!S[u])printf("r%d ",u);
for(int v=1;v<=m;v++)if(T[v])printf("c%d ",v);
}
int main(){
freopen("in.txt","r",stdin);
cin>>n>>m;
int t;cin>>t;
while(t--){
int x,y;
cin>>x>>y;
link[x][y]=1;
}
Maxmatch();
}