题意:
在一个n*n的矩阵中(n<=100)..每个格子放了一种颜色的气球(颜色用数字1~50表示)...每次的操作是消除一行或者一列颜色相同的气球.问经过k次操作..哪些颜色的气球还存在...
题解:
每种颜色分开来求...做边(x,y)....由于对于一个气球(x,y)..只要它x被用了或者y被用了..那么这个气球也就消除了...题目转化为最少要用多少个点..使得所有的边都覆盖..也就是经典的二分图最小点覆盖问题...等价为求二分图的最大匹配数...
Program:
#include<iostream> #include<stdio.h> #include<algorithm> #include<cmath> #include<stack> #include<queue> #define ll long long #define MAXN 105 using namespace std; int n,match[MAXN]; bool arc[MAXN][MAXN],inmap[MAXN],used[MAXN],s[MAXN][MAXN]; bool dfs(int x) { int i; for (i=1;i<=n;i++) if (arc[x][i] && !used[i]) { used[i]=true; if (!match[i] || dfs(match[i])) { match[i]=x; return true; } } return false; } int getmax() { int sum=0; memset(match,0,sizeof(match)); for (int i=1;i<=n;i++) { memset(used,false,sizeof(used)); sum+=dfs(i); } return sum; } int main() { int i,j,k,ans; bool f; while (~scanf("%d%d",&n,&k) && n) { memset(inmap,false,sizeof(inmap)); for (i=1;i<=n;i++) for (j=1;j<=n;j++) scanf("%d",&s[i][j]),inmap[s[i][j]]=true; f=false; for (int t=1;t<=50;t++) if (inmap[t]) { memset(arc,false,sizeof(arc)); for (i=1;i<=n;i++) for (j=1;j<=n;j++) if (s[i][j]==t) arc[i][j]=true; if (getmax()>k) { if (!f) printf("%d",t); else printf(" %d",t); f=true; } } if (!f) printf("-1"); printf("\n"); } return 0; }