zoukankan      html  css  js  c++  java
  • HDU 1281

    题目链接:http://acm.split.hdu.edu.cn/showproblem.php?pid=1281

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

    Problem Description
    小希和Gardon在玩一个游戏:对一个N*M的棋盘,在格子里放尽量多的一些国际象棋里面的“车”,并且使得他们不能互相攻击,这当然很简单,但是Gardon限制了只有某些格子才可以放,小希还是很轻松的解决了这个问题(见下图)注意不能放车的地方不影响车的互相攻击。 
    所以现在Gardon想让小希来解决一个更难的问题,在保证尽量多的“车”的前提下,棋盘里有些格子是可以避开的,也就是说,不在这些格子上放车,也可以保证尽量多的“车”被放下。但是某些格子若不放子,就无法保证放尽量多的“车”,这样的格子被称做重要点。Gardon想让小希算出有多少个这样的重要点,你能解决这个问题么?
     
    Input
    输入包含多组数据, 
    第一行有三个数N、M、K(1<N,M<=100 1<K<=N*M),表示了棋盘的高、宽,以及可以放“车”的格子数目。接下来的K行描述了所有格子的信息:每行两个数X和Y,表示了这个格子在棋盘中的位置。
     
    Output
    对输入的每组数据,按照如下格式输出: 
    Board T have C important blanks for L chessmen.
     
    Sample Input
    3 3 4
    1 2
    1 3
    2 1
    2 2
    3 3 4
    1 2
    1 3
    2 1
    3 2
     
    Sample Output
    Board 1 have 0 important blanks for 2 chessmen.
    Board 2 have 3 important blanks for 3 chessmen.
     
    题解:
    参考http://www.cnblogs.com/dilthey/p/7647870.html博文中的方法②;
    因为这次没有墙能隔开车与车之间的攻击,故直接将整行整列缩成点,然后求出max match;
    但是如何寻找其中的“必须边”呢?
    比较好想的方法就是直接暴力枚举最大匹配中的匹配边,如果把它去掉还能不能得到一样的最大匹配数:
    如果不能,就是必须边,cnt+=1;
     
    AC代码:
     1 #include<cstdio>
     2 #include<cstring>
     3 #include<vector>
     4 #define MAX 203
     5 using namespace std;
     6 int n,m,k;
     7 int edge[MAX][MAX];
     8 int matching[MAX];
     9 int vis[MAX];
    10 void init(){memset(edge,0,sizeof(edge));}
    11 void add_edge(int u,int v){edge[u][v]=edge[v][u]=1;}
    12 bool dfs(int u)
    13 {
    14     for(int v=1;v<=n+m;v++)
    15     {
    16         if(!edge[u][v]) continue;
    17         if (!vis[v])
    18         {
    19             vis[v]=1;
    20             if(!matching[v] || dfs(matching[v]))
    21             {
    22                 matching[v]=u;
    23                 matching[u]=v;
    24                 return true;
    25             }
    26         }
    27     }
    28     return false;
    29 }
    30 int hungarian()
    31 {
    32     int ret=0;
    33     memset(matching,0,sizeof(matching));
    34     for(int i=1;i<=n;i++)
    35     {
    36         if(!matching[i])
    37         {
    38             memset(vis,0,sizeof(vis));
    39             if(dfs(i)) ret++;
    40         }
    41     }
    42     return ret;
    43 }
    44 int mp[103][103],match[MAX][MAX];
    45 int main()
    46 {
    47     int kase=0;
    48     while(scanf("%d%d%d",&n,&m,&k)!=EOF)
    49     {
    50         memset(mp,0,sizeof(mp));
    51         for(int i=1,r,c;i<=k;i++)
    52         {
    53             scanf("%d%d",&r,&c);
    54             mp[r][c]=1;
    55         }
    56 
    57         init();
    58         for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) if(mp[i][j]) add_edge(i,j+n);
    59         int max_match=hungarian();
    60 
    61         int cnt=0;
    62         memset(match,0,sizeof(match));
    63         for(int i=1;i<=n+m;i++) for(int j=n+1;j<=n+m;j++) if(matching[i]==j && matching[j]==i) match[i][j]=1;
    64         for(int i=1;i<=n+m;i++)
    65         {
    66             for(int j=n+1;j<=n+m;j++)
    67             {
    68                 if(match[i][j])
    69                 {
    70                     edge[i][j]=0;
    71                     if(hungarian()<max_match) cnt++;
    72                     edge[i][j]=1;
    73                 }
    74             }
    75         }
    76 
    77         printf("Board %d have %d important blanks for %d chessmen.
    ",++kase,cnt,max_match);
    78     }
    79 }
  • 相关阅读:
    这两天自己模仿写的一个Asp.Net的显示分页方法 附加实体转换和存储过程
    JavaScript 删除 ASP.NET 设置的多值 Cookie 的方法
    Http 请求处理流程
    ASP.NET实现二维码(QRCode)的创建和读取
    ASP.NET实现网站的自动升级
    ASP.NET乱码深度剖析
    ASP.net学习总结
    ASP.net MVC基础
    umeditor编辑器复制粘贴图片上传
    fckeditor编辑器复制粘贴图片上传
  • 原文地址:https://www.cnblogs.com/dilthey/p/7663065.html
Copyright © 2011-2022 走看看