50 years, 50 colors
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 3303 Accepted Submission(s): 1851
Problem Description
On Octorber 21st, HDU 50-year-celebration, 50-color balloons floating around the campus, it's so nice, isn't it? To celebrate this meaningful day, the ACM team of HDU hold some fuuny games. Especially, there will be a game named "crashing color balloons".
There will be a n*n matrix board on the ground, and each grid will have a color balloon in it.And the color of the ballon will be in the range of [1, 50].After the referee shouts "go!",you can begin to crash the balloons.Every time you can only choose one kind of balloon to crash, we define that the two balloons with the same color belong to the same kind.What's more, each time you can only choose a single row or column of balloon, and crash the balloons that with the color you had chosen. Of course, a lot of students are waiting to play this game, so we just give every student k times to crash the balloons.
Here comes the problem: which kind of balloon is impossible to be all crashed by a student in k times.
Input
There will be multiple input cases.Each test case begins with two integers n, k. n is the number of rows and columns of the balloons (1 <= n <= 100), and k is the times that ginving to each student(0 < k <= n).Follow a matrix A of n*n, where Aij denote the color of the ballon in the i row, j column.Input ends with n = k = 0.
Output
For each test case, print in ascending order all the colors of which are impossible to be crashed by a student in k times. If there is no choice, print "-1".
Sample Input
1 1 1 2 1 1 1 1 2 2 1 1 2 2 2 5 4 1 2 3 4 5 2 3 4 5 1 3 4 5 1 2 4 5 1 2 3 5 1 2 3 4 3 3 50 50 50 50 50 50 50 50 50 0 0
Sample Output
-1 1 2 1 2 3 4 5 -1
Author
8600
Source
“2006校园文化活动月”之“校庆杯”大学生程序设计竞赛暨杭州电子科技大学第四届大学生程序设计竞赛
Recommend
LL
题意:n*n的矩阵,分布着各种颜色的气球,k次操作:每次操作扎破一行或一列的同一颜色的气球。问在k次操作后有那几种颜色的气球是不能被完全扎破的.
分析:
问题类似:HDU 2119 Matrix
我们只需要对于每种颜色判断一下该颜色的气球最少需要多少次才能全部扎破即可,如果大于k,则记录下来ans,如上题一样,我们把行标号放左点集,列标号放右点集合. 如果(i,j)格子的颜色为当前检验col,那么就连一条左i与右j点的边.
由于我们每次可以消灭一行或一列的所有同色气球,那么我们只需要选出尽量少的行号或列号,然后看看这些行号或列号是否正好已经把所有为当前颜色气球都覆盖了,即最小点覆盖=最大匹配数
//二分图最大匹配模板,二分图都是无向图
//调用下面算法前,保证本图是二分图
/*************vecotr模板*****************/
#include<cstdio>
#include<iostream>
#include<fstream>
#include<algorithm>
#include<functional>
#include<cstring>
#include<string>
#include<cstdlib>
#include<iomanip>
#include<numeric>
#include<cctype>
#include<cmath>
#include<ctime>
#include<queue>
#include<stack>
#include<list>
#include<set>
#include<map>
using namespace std;
const int maxn = 110;
set<int> color;
struct Max_Match
{
int n,m;//左右点集大小,点从1开始编号
int mapp[maxn][maxn];
bool vis[maxn];//vis[i]表示右边第i个点是否在本次match中被访问过
int left[maxn];//left[i]==j表右边第i个点与左边第j个点匹配,为-1表无点匹配
int col;
void init(int n,int m)
{
this->n = n;
memset(left, -1, sizeof(left));
}
//判断从左u点是否可以找到一条增广路
bool match(int u)
{
for (int v = 1;v<=n; v++)
{
if (!vis[v]&&mapp[u][v]==col)
{
vis[v] = true;
if (left[v] == -1 || match(left[v]))//找到增广路
{
left[v] = u;
return true;
}
}
}
return false;
}
//返回当前二分图的最大匹配数
int solve()
{
int ans = 0;//最大匹配数
for (int i = 1; i <= n; i++)//每个左边的节点找一次增广路
{
memset(vis, 0, sizeof(vis));
if (match(i)) ans++;//找到一条增广路,形成一个新匹配
}
return ans;
}
}MM;
/*************vecotr模板*****************/
int main()
{
int n, m;
while (scanf("%d%d", &n,&m)!=-1 )
{
if (n == 0 && m == 0) break;
color.clear();
for (int i = 1; i <= n; i++)
for (int j = 1; j <= n; j++)
{
scanf("%d", &MM.mapp[i][j]);
color.insert(MM.mapp[i][j]);
}
MM.init(n, 0);
vector<int> ans;
for (set<int>::iterator it = color.begin(); it != color.end(); it++)
{
MM.col = *it;
MM.init(n,0);
if (MM.solve() > m)
{
ans.push_back(*it);
}
}
if (ans.size() == 0) printf("-1\n");
else
{
for (int j = 0; j < ans.size()-1; j++)
printf("%d ", ans[j]);
printf("%d\n", ans[ans.size()-1]);
}
}
return 0;
}