HDU149850 years, 50 colors(行列匹配+最小点覆盖)

题意:给出一个n*n的矩阵,里面的数字代表气球的颜色,你每次可以一行或者一列里的相同的某一颜色气球,并把它们全部打破,你一共有k次机会,问最后不能被某一位学生在k次操作里打破的气球,按字典序升序输出,没有的话输出-1 思路:我们反过来想,能被学生在K次里打破的话,那么这些气球的分布行列数必然不大于K,,我们就以某一色气球的 X,Y建立二分图 ,X,Y对应二分图的左右两边,我们肯定是要选择最少点来覆盖所有的边,最小点覆盖就是最大匹配,然后枚举所有颜色的点即可

;const int maxn=150;const int inf=9999999;const int mod=100007;int G[maxn][maxn];int a[maxn][maxn];int matching[maxn];bool vis[maxn];int n,k;bool dfs(int u){for(int i=0;i<n;i++)if(G[u][i]){int v=i;if(vis[v])continue;vis[v]=true;if(matching[v]==-1||dfs(matching[v])){matching[v]=u;return true;}}return false;}int hungar(){int ans=0;cl(matching,-1);for(int i=0;i<n;i++){cl(vis,false);if(dfs(i))ans++;}return ans;}int main(){while(~scanf(“%d%d”,&n,&k)&&(n||k)){for(int i=0;i<n;i++){for(int j=0;j<n;j++){scanf(“%d”,&a[i][j]);}}vector<int> v;for(int color=1;color<=50;color++){//枚举颜色cl(G,0);for(int i=0;i<n;i++){for(int j=0;j<n;j++)if(a[i][j]==color){G[i][j]=1;//建立这个color颜色的二分图}}int t=hungar();//计算if(t>k){v.pb(color);}}if(v.empty()){puts(“-1”);}else {printf(“%d”,v[0]);for(int i=1;i<v.size();i++){printf(” %d”,v[i]);}printf(“\n”);}}return 0;}

我只愿,在你的理想和希望里能为你增加一点鼓励,

HDU149850 years, 50 colors(行列匹配+最小点覆盖)

相关文章:

你感兴趣的文章:

标签云: