您的位置:首页 > 其它

hdoj 1498 50 years, 50 colors 【最小点覆盖】

2015-05-12 16:39 417 查看

50 years, 50 colors

Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)

Total Submission(s): 1830 Accepted Submission(s): 1003



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



题意:给出N*N个方格,每个格子都有一种颜色,颜色号从1—50。对于出现的任一种颜色,若你不可以在k次操作内让该颜色消失(对于全部带有该颜色的格子),那么就输出该颜色的编号,输出时从小到大输出;若可以在k次操作涂掉所有出现的颜色输出-1。
涂色规则:一次操作只能涂掉一行或者一列中的相同颜色。

对于任意坐标(x,y),若它和(x,任意)同色,那么一次操作便可消去这两个格子的颜色,同理(任意,y)亦是如此。
为什么会这样?因为对于任意坐标(x,y),我们都可以把x,y看做是两个已经连通的点,对于(x,任意)都可以看做是 一个与x相连的点,(任意,y)亦是如此。

这样就可以简化题目-->求二分图的最小点覆盖(用最少的点覆盖所有的边,一条边被覆盖指至少有一个与它相邻的点被选中)。

枚举所有出现的颜色+二分图匹配模板就ok了:

邻接矩阵:
#include<stdio.h>
#include<string.h>
#include<math.h>
#include<stdlib.h>
#include<queue>
#include<stack>
#include<algorithm>
using namespace std;
int map[110][110],pipei[110],used[110];
int color[110][110];
int vis[51];//记录该颜色有没有出现 
int n,k;
int find(int x)
{
	int i,j;
	for(i=1;i<=n;i++)
	{
		if(!used[i]&&map[x][i])
		{
			used[i]=1;
			if(!pipei[i]||find(pipei[i]))
			{
				pipei[i]=x;
				return 1;
			}
		}
	}
	return 0;
}
int solve()//求最小路径覆盖 
{
	int i;
	int sum=0;
	memset(pipei,0,sizeof(pipei));
	for(i=1;i<=n;i++)
	{
		memset(used,0,sizeof(used));
		sum+=find(i);
	}
	return sum;
}
int main()
{
	int i,j;
	int col;
	int exist;
	while(scanf("%d%d",&n,&k)&&(n!=0||k!=0))
	{
		memset(vis,0,sizeof(vis));
		for(i=1;i<=n;i++)
		{
			for(j=1;j<=n;j++)
			{
				scanf("%d",&color[i][j]);
				vis[color[i][j]]=1;//该颜色出现 
			}
		}
		exist=0;//若全部颜色都不可以被消掉为0,否则为1 
		for(col=1;col<=50;col++)//枚举所有颜色 
		{
			if(vis[col])//该颜色出现过
			{
				memset(map,0,sizeof(map));//每次初始化 
				for(i=1;i<=n;i++)
				{
					for(j=1;j<=n;j++)
					{
						if(color[i][j]==col)
						{
							map[i][j]=1;
						}
					}
				}
				if(solve()>k)//该颜色不能在k次操作去掉 
				{
					exist++; 
					if(exist>1)
					printf(" ");
					printf("%d",col);
				}
			} 
		}
		if(!exist)
		printf("-1");
		printf("\n");
	}
	return 0;
}


邻接表:
#include<stdio.h>
#include<string.h>
#include<math.h>
#include<stdlib.h>
#include<queue>
#include<stack>
#include<vector> 
#include<algorithm>
using namespace std;
vector<int >map[110];
int pipei[110],used[110];
int color[110][110];
int vis[51];//记录该颜色有没有出现 
int n,k;
int find(int x)
{
	int i,j;
	int t;
	for(i=0;i<map[x].size();i++)
	{
		t=map[x][i];
		if(!used[t])
		{
			used[t]=1;
			if(!pipei[t]||find(pipei[t]))
			{
				pipei[t]=x;
				return 1;
			}
		}
	}
	return 0;
}
int solve()//求最小路径覆盖 
{
	int i;
	int sum=0;
	memset(pipei,0,sizeof(pipei));
	for(i=1;i<=n;i++)
	{
		memset(used,0,sizeof(used));
		sum+=find(i);
	}
	return sum;
}
int main()
{
	int i,j;
	int col;
	int exist;
	while(scanf("%d%d",&n,&k)&&(n!=0||k!=0))
	{
		memset(vis,0,sizeof(vis));
		for(i=1;i<=n;i++)
		{
			for(j=1;j<=n;j++)
			{
				scanf("%d",&color[i][j]);
				vis[color[i][j]]=1;//该颜色出现 
			}
		}
		exist=0;//若全部颜色都不可以被消掉为0,否则为1 
		for(col=1;col<=50;col++)//枚举所有颜色 
		{
			if(vis[col])//该颜色出现过
			{
				for(i=1;i<=n;i++)
				{
					map[i].clear();//清空邻接表 
					for(j=1;j<=n;j++)
					{
						if(color[i][j]==col)
						{
							map[i].push_back(j);
						}
					}
				}
				if(solve()>k)//该颜色不能在k次操作去掉 
				{
					exist++; 
					if(exist>1)
					printf(" ");
					printf("%d",col);
				}
			} 
		}
		if(!exist)
		printf("-1");
		printf("\n");
	}
	return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: