顶点分为两个集合X和Y,所有的边关联在两个顶点中,恰好一个属于集合X,另一个属于集合Y。
最小覆盖:最小覆盖要求用最少的点(X集合或Y集合的都行)让每条边都至少和其中一个点关联。 可以证明:最少的点(即覆盖数)=最大匹配数
Konig定理:二分图的最小顶点覆盖数等于最大匹配数。
wa
#include<bits/stdc++.h>
using namespace std;
int n,m;
int Map[110][110],vis[110],d[110];
int find(int x){
for(int i=0;i<m;i++){
if(Map[x][i]==1&&!vis[i]){
vis[i]=1;
if(d[i]==-1){
d[i]=x;
return true;
}
else{
if(find(d[i])==true){
d[i]=x;
return true;
}
}
}
}
return false;
}
int main(){
int k,i,x,y,ans;
while(scanf("%d%d%d",&n,&m,&k)&&n){
ans=0;
memset(Map,0,sizeof(Map));
memset(d,-1,sizeof(d));
for(int j=0;j<k;j++){
scanf("%d%d%d",&i,&x,&y);
Map[x][y]=1;
}
for(i=0;i<n;i++){
memset(vis,0,sizeof(vis));
if(find(i)==true)ans++;
}
printf("%d\n",ans);
}
return 0;
}
wa
#include<bits/stdc++.h>
using namespace std;
int n,m;
int Map[110][110],vis[110],d[110];
int find(int x){
for(int i=0;i<m;i++){
if(Map[x][i]==1&&!vis[i]){
vis[i]=1;
if(d[i]==-1){
d[i]=x;
return true;
}
else{
if(find(d[i])==true){
d[i]=x;
return true;
}
}
}
}
return false;
}
int main(){
int k,i,x,y,ans;
while(scanf("%d",&n)!=EOF){
if(n==0)break;
scanf("%d%d",&m,&k);
ans=0;
memset(Map,0,sizeof(Map));
memset(d,-1,sizeof(d));
for(int j=0;j<k;j++){
scanf("%d%d%d",&i,&x,&y);
Map[x][y]=1;
}
for(i=0;i<n;i++){
memset(vis,0,sizeof(vis));
if(find(i)==true)ans++;
}
printf("%d\n",ans);
}
return 0;
}
ac:
#include<bits/stdc++.h>
using namespace std;
int n,m;
int Map[110][110],vis[110],d[110];
int find(int x){
for(int i=1;i<=m;i++){
if(Map[x][i]==1&&!vis[i]){
vis[i]=1;
if(d[i]==-1){
d[i]=x;
return true;
}
else{
if(find(d[i])==true){
d[i]=x;
return true;
}
}
}
}
return false;
}
int main(){
int k,i,x,y,ans;
while(scanf("%d",&n)!=EOF){
if(n==0)break;
scanf("%d%d",&m,&k);
ans=0;
memset(Map,0,sizeof(Map));
memset(d,-1,sizeof(d));
for(int j=0;j<k;j++){
scanf("%d%d%d",&i,&x,&y);
Map[x][y]=1;
}
for(i=1;i<=n;i++){
memset(vis,0,sizeof(vis));
if(find(i)==true)ans++;
}
printf("%d\n",ans);
}
return 0;
}