和击毁小行星的那道题是一样的,只不过这道题要输出路径。
最小点覆盖 = 最大匹配数
求一个最小覆盖点集
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
const int N=1111;
int n1,n2,k;
int mp[N][N],vis[N],link[N];
int vis2[N];
int v[N];
int dfs(int x)
{
int i;
vis2[x]=1;
for(i=1; i<=n2; i++)
{
if(!mp[x][i]&&!vis[i])
{
vis[i]=1;
if(link[i]==-1||dfs(link[i]))
{
link[i]=x;
return 1;
}
}
}
return 0;
}
int main()
{
int i,x,y,s;
int cas = 0;
while(scanf("%d%d%d",&n1,&n2,&k)&&n1){
s=0;
for(int i=1;i<=n1;i++){
for(int j=1;j<=n2;j++){
mp[i][j]=1;
}
}
for(i=0; i<k; i++)
{
scanf("%d%d",&x,&y);
mp[x][y]=0;
}
memset(link,-1,sizeof(link));
for(i=1; i<=n1; i++)
{
memset(vis,0,sizeof(vis));
if(dfs(i))
s++;
}
memset(vis,0,sizeof(vis));
memset(vis2,0,sizeof(vis2));
memset(v,0,sizeof(v));
for(int i=1;i<=n2;i++){
v[link[i]]=1;
printf("link[%d] :%d\n",i,link[i]);
}
for(int i=1;i<=n1;i++){
if(!v[i])
dfs(i);
}
printf("%d",s);
for(int i=1;i<=n1;i++){
if(!vis2[i])
printf(" r%d",i);
}
for(int i=1;i<=n2;i++){
if(vis[i])
printf(" c%d",i);
}
puts("");
}
return 0;
}