50 years, 50 colors 【最小顶点覆盖】

来源:互联网 发布:slideunlock.js 编辑:程序博客网 时间:2024/05/21 17:53

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。
涂色规则:一次操作只能涂掉一行或者一列中的相同颜色。

题解
首先 我们可以简化的想一下这道题目,假设题目中只有一种颜色,不过是只有 一部分的格子上有颜色,问是否可以在k次操作后这个颜色 被删完。 将 行 当作二分图的 左侧匹配,将 列 当作二分图的右侧匹配。 如果(x,y)处有颜色,做出有向边x–>y
当所有的边都画完之后,仔细想一下,是不是 就可以转化为 最小定点覆盖问题 。。
综上 ,将其推到n种颜色,每次遍历一种颜色,就可以了。

代码

#include<cstdio>#include<cstring>#include<algorithm>#include<iostream>#include<cmath>#include<queue>#include<stack>#include<map>#include<vector>#include<set>#define CLR(a,b) memset((a),(b),sizeof(a))#define inf 0x3f3f3f3f#define mod 100009#define LL long long#define MAXN  10000+10#define MAXM 2000000+100#define ll o<<1#define rr o<<1|1#define lson o<<1,l,mid#define rson o<<1|1,mid+1,rusing namespace std;void read(int &x){    x=0;char c;    while((c=getchar())<'0');    do x=x*10+c-'0';while((c=getchar())>='0');}struct Edge{    int from,to,next;}edge[MAXN];int head[MAXN],top;int vis[MAXN],pi[MAXN];int mp[105][105];int n,m,k;set<int>S;  //  这里我用的是 set ,可以去重,而且是有序的 ,很方便。void init(){    memset(pi,0,sizeof(pi));    memset(head,-1,sizeof(head));    top=0;}void addedge(int a,int b){    Edge e={a,b,head[a]};    edge[top]=e;head[a]=top++;}void getmap(){    for(int i=1;i<=n;i++)    {        for(int j=1;j<=n;j++)        {            int c;            scanf("%d",&c);            mp[i][j]=c;            S.insert(c);  // 插入颜色        }    }}int find(int x){    for(int i=head[x];i!=-1;i=edge[i].next)    {        Edge e=edge[i];        if(!vis[e.to])        {            vis[e.to]=1;            if(!pi[e.to]||find(pi[e.to]))            {                pi[e.to]=x;                return 1;            }        }    }    return 0;}int pipei()  //返回 每一种颜色 匹配多少{    int sum=0;    for(int i=1;i<=n;i++)    {        memset(vis,0,sizeof(vis));        sum+=find(i);    }    return sum;}void solve(){    int ge=0;    set<int>::iterator it=S.begin(); //set迭代器    for(;it!=S.end();it++)    {        int color=*it;  //按序 得到颜色        init();  //初始化         for(int i=1;i<=n;i++) // 遍历图 得到二分图        {            for(int j=1;j<=n;j++)            {                if(mp[i][j]==color)                {                    addedge(i,j);                }            }        }        int sum=pipei();        int have=0;  // 用来控制每两个数字之间的空格        if(sum>k)  //不能够删完        {            ge++;            if(have++) putchar(' ');            printf("%d",color);        }    }    if(!ge) printf("-1\n"); //没有不能删完的,就输出 -1    else putchar('\n');}int main(){    while(scanf("%d%d",&n,&k)&&(n||k))    {        S.clear();        memset(mp,0,sizeof(mp));        getmap();        solve();    }    return 0;}
原创粉丝点击