考察:枚举,最小覆盖点数 = 最大匹配。
思路:枚举每一种颜色,如果该颜色的最小覆盖点大于规定时间K,说明不能够在时间内消除完,即为答案。因为在单位时间里可以消除一行或者一列中相同的颜色,建图的时候,将每个点的横坐标去匹配其纵坐标即可(既完成了消除整行或者整列的目的)。由于题目要求将结果从小到大输出,那么可以用STL里的set来完成枚举并自动排序。

1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <set> 5 #define MAX 105 6 7 using namespace std; 8 9 set<int> S; 10 set<int>::iterator iter; 11 bool cnt[MAX][MAX]; 12 int link[MAX]; 13 bool used[MAX]; 14 int map[MAX][MAX]; 15 int ans[MAX]; 16 int N,K,index; 17 18 bool dfs(int left) 19 { 20 for(int i=1;i<=N;i++) 21 { 22 if(cnt[left][i] && !used[i]) 23 { 24 used[i]=true; 25 if(link[i]==-1 || dfs(link[i])) 26 { 27 link[i]=left; 28 return true; 29 } 30 } 31 } 32 return false; 33 } 34 35 int Match() 36 { 37 memset(link,-1,sizeof(link)); 38 int ret=0; 39 for(int i=1;i<=N;i++) 40 { 41 memset(used,0,sizeof(used)); 42 if(dfs(i)) 43 ret ++; 44 } 45 return ret; 46 } 47 48 int main() 49 { 50 while(~scanf("%d%d",&N,&K)) 51 { 52 if(!N && !K) 53 break; 54 S.clear(); 55 index=0; 56 for(int i=1;i<=N;i++) 57 { 58 for(int j=1;j<=N;j++) 59 { 60 scanf("%d",&map[i][j]); 61 S.insert(map[i][j]); 62 } 63 } 64 for(iter=S.begin();iter!=S.end();iter++) 65 { 66 for(int i=1;i<=N;i++) 67 { 68 for(int j=1;j<=N;j++) 69 { 70 if(map[i][j]==(*iter)) 71 cnt[i][j]=true; 72 else 73 cnt[i][j]=false; 74 } 75 } 76 int temp=Match(); 77 if(temp>K) 78 ans[index++]=(*iter); 79 } 80 if(index==0) 81 printf("-1\n"); 82 else 83 { 84 for(int i=0;i<index;i++) 85 { 86 printf("%d",ans[i]); 87 if(i!=index-1) 88 printf(" "); 89 } 90 printf("\n"); 91 } 92 } 93 return 0; 94 }