二分图最小覆盖数=最大匹配数
建模后即可
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
struct my{
int next;
int v;
};
const int maxn=1000000+10;
const int maxn2=1000+5;
my bian[maxn];
int adj[maxn];
int s[maxn2];
int t[maxn2];
int n,m;
int left[maxn2];
int right[maxn2];
int fa;
int top1;
int top2;
int ansx[maxn2],ansy[maxn2];
void init(){
memset(bian,0,sizeof(bian));
memset(adj,0,sizeof(adj));
fa=0;
}
void myinsert(int u,int v){
bian[++fa].v=v;
bian[fa].next=adj[u];
adj[u]=fa;
}
bool match(int i){
s[i]=true;
for (int j=adj[i];j;j=bian[j].next){
int v=bian[j].v;
if(!t[v]){
t[v]=true;
if(left[v]==-1 || match(left[v])){
left[v]=i;
right[i]=v;
return true;
}
}
}
return false;
}
int KM(){
top1=0;
memset(left,-1,sizeof(left));
memset(right,-1,sizeof(right));
int ans=0;
for (int i=1;i<=n;i++){
memset(s,0,sizeof(s));
memset(t,0,sizeof(t));
if(match(i))
ans++;
}
memset(s,0,sizeof(s));
memset(t,0,sizeof(t));
for (int i=1;i<=n;i++){
if(right[i]==-1) match(i);
}
for (int i=1;i<=n;i++) if(!s[i]) ansx[++top1]=i;
top2=0;
for (int j=1;j<=m;j++) if(t[j]) ansy[++top2]=j;
return ans;
}
void print()
{
for (int i=1;i<=top1;i++) printf(" r%d",ansx[i]);
for (int j=1;j<=top2;j++) printf(" c%d",ansy[j]);
printf("\n");
}
int main(){
int R,C,N,r,c;
while(scanf("%d%d%d",&R,&C,&N) && R && C && N){
init();
n=R;
m=C;
for (int i=1;i<=N;i++){
scanf("%d%d",&r,&c);
myinsert(r,c);
}
printf("%d",KM());
print();
}
return 0;
}