1 112 11 11 22 11 22 25 41 2 3 4 52 3 4 5 13 4 5 1 24 5 1 2 35 1 2 3 43 350 50 5050 50 5050 50 500 0 Sample Output-1121 2 3 4 5-1 题目大意:给你一个n*n的矩阵,矩阵中每个格子对应一种颜色的气球,问你踩n次,每次只能选择一行或一列踩掉一种颜色的所有气球,最后还剩余的气球颜色有哪些
题目思路:
首先看下数据范围,气球颜色只有50种最多,矩阵大小100*100最大,所以我们可以枚举每种颜色,对于每种颜色,我们进行行列匹配,x为一个集合,y为一个集合,最后匹配到的最大匹配数就是踩掉所有气球所需的最小次数,这个应该不难想到,如果画个图来理解就是最小点覆盖,而最小点覆盖=最大匹配!
AC代码:
#include<algorithm>#include<iostream>#include<cstring>#include<cstdio>using namespace std;const int maxn = 105;int n,k;int link[maxn],a[55],matrix[maxn][maxn];bool vis[maxn],mp[maxn][maxn];bool dfs(int u){ for(int i=1;i<=n;i++){ if(!vis[i]&&mp[u][i]){ vis[i]=true; if(link[i]==-1||dfs(link[i])){ link[i]=u; return true; } } } return false;}int main(){ while(scanf("%d%d",&n,&k),n+k){ memset(a,0,sizeof(a)); for(int i=1;i<=n;i++){ for(int j=1;j<=n;j++){ scanf("%d",&matrix[i][j]); a[matrix[i][j]]=1; } } int flag=1; for(int i=1;i<=50;i++){ if(!a[i])continue; //枚举每种颜色,a[i]记录该种颜色有没有出现过 memset(mp,false,sizeof(mp)); memset(link,-1,sizeof(link)); int num = 0; for(int j=1;j<=n;j++) for(int l=1;l<=n;l++) if(matrix[j][l]==i)mp[j][l]=true; for(int j=1;j<=n;j++){ memset(vis,false,sizeof(vis)); if(dfs(j))num++; } if(num>k){ if(flag){printf("%d",i);flag=0;} else printf(" %d",i); } } if(flag)printf("-1"); printf("/n"); } return 0;}
新闻热点
疑难解答