zoukankan      html  css  js  c++  java
  • hdu 1498 50 years, 50 colors(二分匹配,最小点覆盖)

    题意:n*n的矩阵放置不同的颜色(不同的数字代表不同的颜色),你有k次选择,每一次只能选择某一行或某一列,可以消除该行(列)的所有颜色,问有哪几种颜色,无论怎样经过k次选择后依然无法完全抹去。

    分析:依旧是将横坐标作为x集,纵坐标作为y集合进行匹配。对于某种颜色的匹配,如果他的最大匹配大于k,则该颜色在k次里无论如何都无法抹去的。

             还有一个问题就是为什么这道题是最小点覆盖,通过自己画图就知道了

            假设x{1}和{1,2,3,4}分别连接,x{2}和y{3}连接,则只用选择1,2行,就可以将所有的颜色抹去了

    View Code
     1 #include<stdio.h>
     2 #include<string.h>
     3 #include<algorithm>
     4 using namespace std;
     5 const int MAXN=150;
     6 int map[MAXN][MAXN];
     7 int pre[MAXN];
     8 int vis[MAXN];
     9 int used[MAXN];
    10 int ans[MAXN];
    11 int n,k;
    12 
    13 bool cmp(int a,int b)
    14 {
    15     return a<b;
    16 }
    17 
    18 int find(int cur,int color)
    19 {
    20     int i;
    21     for(i=1; i<=n; i++)
    22     {
    23         if(map[cur][i]==color && !vis[i])//对应的某一列是否存在该color
    24         {
    25             vis[i]=1;
    26             if(pre[i]==-1 || find(pre[i],color))//这里find的是pre【i】,刚开始这里敲错了wa了两次
    27             {
    28                 pre[i]=cur;
    29                 return 1;
    30             }
    31         }
    32     }
    33     return 0;
    34 }
    35 
    36 int main()
    37 {
    38     int i,j,t,w,sum;
    39     int len;
    40     while(scanf("%d%d",&n,&k))
    41     {
    42         if(n==0 && k==0) break;
    43         memset(map,0,sizeof(map));
    44         memset(used,0,sizeof(used));
    45 
    46         for(i=1; i<=n; i++)
    47         {
    48             for(j=1; j<=n; j++)
    49             {
    50                 scanf("%d",&w);
    51                 map[i][j]=w;
    52             }
    53         }
    54         len=0;
    55         for(i=1; i<=n; i++)
    56         {
    57             for(j=1; j<=n; j++)
    58             {
    59                 memset(pre,-1,sizeof(pre));
    60                 sum=0;
    61                 if(used[map[i][j]]==0)//该颜色没有出现过
    62                 {
    63                     used[map[i][j]]=1;
    64                     for(t=1; t<=n; t++)//枚举每一行
    65                     {
    66                         memset(vis,0,sizeof(vis));
    67                         sum+=find(t,map[i][j]);
    68                     }
    69                 }
    70                 if(sum>k) ans[len++]=map[i][j];
    71             }
    72         }
    73         if(len==0) printf("-1\n");
    74         else
    75         {
    76             sort(ans,ans+len,cmp);
    77             for(i=0;i<len;i++)
    78             {
    79                 if(i) printf(" ");
    80                 printf("%d",ans[i]);
    81             }
    82             printf("\n");
    83         }
    84     }
    85 }

     set容器

    View Code
     1 #include<stdio.h>
     2 #include<string.h>
     3 #include<set>
     4 #include<algorithm>
     5 #include<iostream>
     6 using namespace std;
     7 
     8 const int MAXN=150;
     9 
    10 set<int>s;
    11 int map[MAXN][MAXN];
    12 int pre[MAXN];
    13 int vis[MAXN];
    14 int used[MAXN];
    15 int ans[MAXN];
    16 int n,k;
    17 
    18 int find(int cur,int color)
    19 {
    20     int i;
    21     for(i=1; i<=n; i++)
    22     {
    23         if(map[cur][i]==color && !vis[i])
    24         {
    25             vis[i]=1;
    26             if(pre[i]==-1 || find(pre[i],color))
    27             {
    28                 pre[i]=cur;
    29                 return 1;
    30             }
    31         }
    32     }
    33     return 0;
    34 }
    35 
    36 int main()
    37 {
    38     int i,j,t,w,sum;
    39     int len;
    40     while(scanf("%d%d",&n,&k))
    41     {
    42         s.clear();
    43         if(n==0 && k==0) break;
    44         memset(map,0,sizeof(map));
    45 
    46         for(i=1; i<=n; i++)
    47         {
    48             for(j=1; j<=n; j++)
    49             {
    50                 scanf("%d",&w);
    51                 s.insert(w);
    52                 map[i][j]=w;
    53             }
    54         }
    55         len=0;
    56         sum=0;
    57         set<int>::iterator iter;
    58         for(iter=s.begin(); iter!=s.end(); iter++)
    59         {
    60             //cout<<"值"<<*iter<<endl;
    61             memset(pre,-1,sizeof(pre));
    62             sum=0;//这里忘记了
    63             for(t=1; t<=n; t++)
    64             {
    65                 memset(vis,0,sizeof(vis));
    66                 sum+=find(t,*iter);
    67             }
    68             if(sum>k) ans[len++]=*iter;
    69         }
    70         if(len==0) printf("-1\n");
    71         else
    72         {
    73             for(i=0; i<len; i++)
    74             {
    75                 if(i) printf(" ");
    76                 printf("%d",ans[i]);
    77             }
    78             printf("\n");
    79         }
    80     }
    81 }
  • 相关阅读:
    【强烈推荐】 超漂亮的仿腾讯弹出层效果(兼容主流浏览器<转>;
    必须掌握的八个【cmd 命令行】
    grep命令的用法
    sed 命令的用法1
    Paste命令的用法
    uniq命令的用法
    join命令的用法
    Sort命令的用法
    cut命令的用法
    tr命令学习
  • 原文地址:https://www.cnblogs.com/zsboy/p/2876587.html
Copyright © 2011-2022 走看看