uva 11419 (二分图最小覆盖)

二分图最小覆盖数=最大匹配数

建模后即可

#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;
}

posted @ 2018-01-30 11:27  lmjer  阅读(109)  评论(0编辑  收藏  举报