hdu 1498 最小覆盖点数

题意:
 给你一个n*n的矩阵,在矩阵中分布着s种颜色的气球,给你k次扎破气球
 的操作,每次操作可以扎破一行,或一列的同一颜色的气球。问在k次操
 作后有那几种颜色的气球是不能被完全扎破的.
解题:
  利用二分图匹配,寻找每一种颜色对应的最大匹配(行和列分别为X集合,Y集合;map[i,j]代表一个搭配),
  如果大于k则输出"-1",否则输出颜色的递增序列
#include<iostream>
#include<cstdio>
#include<memory.h>
#include<algorithm>
using namespace std;
int vis[502],mat[502];
int n,m,k,tx,ty,map[102][102];
int f[1002][1002],list[102],arr[10002];
int find(int x,int tmp)
{
    for(int i=f[x][0]; i>=1; i--)
    {
        int y=f[x][i];
        if(!vis[y]&&map[x][y]==tmp)
        {
            vis[y]=1;
            if(mat[y]==-1||find(mat[y],tmp))
            {
                mat[y]=x;
                return 1;
            }
        }
    }
    return 0;
}
int main ()
{
    int i,j,t;
    int m,n,k,ans,cnt,cnt1;
    while(scanf("%d%d",&n,&m),(n||m))
    {
        memset(f,0,sizeof(f));
        cnt=0;
        cnt1=0;
        arr[cnt1]=-1;
        for(i=1; i<=n; i++)
        {
            for(j=1; j<=n; j++)
            {
                scanf("%d",&map[i][j]);
                f[i][++f[i][0]]=j;
                for(t=0; t<=cnt1; t++)
                {
                    if(arr[t]==map[i][j]) break;
                }
                if(t>cnt1) arr[++cnt1]=map[i][j];
            }
        }
        int flag=0;
        sort(arr+1,arr+cnt1+1);
        for(i=1; i<=cnt1; i++)
        {
            int Max=0;
            memset(mat,-1,sizeof(mat));
            for(j=1;j<=n;j++)
            {
                memset(vis,0,sizeof(vis));
                if(find(j,arr[i])) Max++;
            }
            if(m<Max)
            {
                flag=1;
                list[cnt++]=arr[i];
            }
        }
        if(flag)
        {
            cout<<list[0];
            for(i=1; i<cnt; i++)
            {
                cout<<" "<<list[i];
            }cout<<endl;
        }else cout<<"-1"<<endl;
    }
    return 0;
}


你可能感兴趣的:(hdu 1498 最小覆盖点数)