zoukankan      html  css  js  c++  java
  • hdu 1281 棋盘游戏 (二分匹配)

    棋盘游戏

    Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
    Total Submission(s): 2137    Accepted Submission(s): 1244


    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.
     
    Author
    Gardon
     
    Source
     
    Recommend
    lcy   |   We have carefully selected several similar problems for you:  1507 1528 1498 1083 1533 
     

    开始看错题意,以为和hdu 1045类似的,后来才发现自己错了。

    把棋盘的行x看成二分图左边的点,列y看成二分图右边的点,那么就把可以放车的位置看成是一条边,而二分图的最大匹配中x互不相同,y互不相同,所以每个匹配都是不同行不同列,所以最大匹配就是最多可以放的车的数量。而要判断有多少个点是必须放的,只要在得出最大匹配后,每次去掉一个匹配,再去运算看得出的结果是否与原来的最大匹配数相同,若相同就不是必须的,若不相同就是必须的。

    按数据规模觉得会TLE,不过没有。

     1 //46MS    276K    1119 B    C++    
     2 #include<stdio.h>
     3 #include<string.h>
     4 #define N 105
     5 int g[N][N];
     6 int lx[N*N],ly[N*N];
     7 int match[N];
     8 int vis[N];
     9 int n,m;
    10 int dfs(int x)
    11 {
    12     for(int i=1;i<=m;i++){
    13         if(!vis[i] && g[x][i]){
    14             vis[i]=1;
    15             if(match[i]==-1 || dfs(match[i])){
    16                 match[i]=x;
    17                 return 1;
    18             }
    19         }
    20     }
    21     return 0;
    22 }
    23 int hungary()
    24 {
    25     int ret=0;
    26     memset(match,-1,sizeof(match));
    27     for(int i=1;i<=n;i++){
    28         memset(vis,0,sizeof(vis));
    29         ret+=dfs(i);
    30     }
    31     return ret;
    32 }
    33 int main(void)
    34 {
    35     int k;
    36     int cas=1;
    37     while(scanf("%d%d%d",&n,&m,&k)!=EOF)
    38     {
    39         memset(g,0,sizeof(g));
    40         for(int i=0;i<k;i++){
    41             scanf("%d%d",&lx[i],&ly[i]);
    42             g[lx[i]][ly[i]]=1;
    43         }
    44         int ans=hungary();
    45         int ret=0;
    46         for(int i=0;i<k;i++){
    47             g[lx[i]][ly[i]]=0;
    48             if(hungary()<ans) ret++;
    49             g[lx[i]][ly[i]]=1;
    50         }
    51         printf("Board %d have %d important blanks for %d chessmen.
    ",cas++,ret,ans);
    52     }
    53     return 0; 
    54 }
  • 相关阅读:
    LeetCode 189. Rotate Array
    LeetCode 965. Univalued Binary Tree
    LeetCode 111. Minimum Depth of Binary Tree
    LeetCode 104. Maximum Depth of Binary Tree
    Windows下MySQL的安装与配置
    LeetCode 58. Length of Last Word
    LeetCode 41. First Missing Positive
    LeetCode 283. Move Zeroes
    《蚂蚁金服11.11:支付宝和蚂蚁花呗的技术架构及实践》读后感
    删除docker下的镜像
  • 原文地址:https://www.cnblogs.com/GO-NO-1/p/3749013.html
Copyright © 2011-2022 走看看