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): 7898    Accepted Submission(s): 4600


    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
     
      1 /*************************************************************************
      2     > File Name: hdu-1281.棋盘游戏.cpp
      3     > Author: CruelKing
      4     > Mail: 2016586625@qq.com 
      5     > Created Time: 2019年08月28日 星期三 09时49分22秒
      6     本题思路:本题的重点在于如何求解重要边,最简单的思路就是枚举所有边,如果去掉一条边之后发现最大匹配数目减少了,则说明这条边所对应的点就是关键点。
      7     其次还有一种复杂度更低的思路,就是对于每个已经匹配过的边,先删除这条边,我们以所有没有匹配过的顶点为起点再去匹配边,如果发现可以匹配到那么就说明还可以找到其他增广路,意思就是可以有别的匹配边代替这条匹配边,那么这个点就不是关键点,否则这个点就是关键点。
      8  ************************************************************************/
      9 /*
     10 #include <cstdio>
     11 #include <cstring>
     12 using namespace std;
     13 
     14 const int maxn = 100 + 5, maxm = 100 * 100 + 5;
     15 int linker[maxn], ui[maxn], vi[maxn];
     16 bool used[maxn], g[maxn][maxn];
     17 int n, m;
     18 
     19 bool dfs(int u) {
     20     for(int v = 1; v <= m; v ++) {
     21         if(g[u][v] && !used[v]) {
     22             used[v] = true;
     23             if(linker[v] == -1 || dfs(linker[v])) {
     24                 linker[v] = u;
     25                 return true;
     26             }
     27         }
     28     }
     29     return false;
     30 }
     31 
     32 int hungary() {
     33     int res = 0;
     34     memset(linker, -1, sizeof linker);
     35     for(int i = 1; i <= n; i ++) {
     36         memset(used, false, sizeof used);
     37         if(dfs(i)) res ++;
     38     }
     39     return res;
     40 }
     41 
     42 int main() {
     43     int k, u, v, Case = 0;
     44     while(~scanf("%d %d %d", &n, &m, &k)) {
     45         memset(g, false, sizeof g);
     46         for(int i = 0; i < k; i ++) {
     47             scanf("%d %d", &ui[i], &vi[i]);
     48             g[ui[i]][vi[i]] = true;
     49         }
     50         int res1 = hungary(), cnt = 0;
     51         for(int i = 0; i < k; i ++) {
     52             g[ui[i]][vi[i]] = false;
     53             int res2 = hungary();
     54             if(res2 < res1) cnt ++;
     55             g[ui[i]][vi[i]] = true;
     56         }
     57         printf("Board %d have %d important blanks for %d chessmen.
    ", ++ Case, cnt, res1);
     58     }
     59     return 0;
     60 }
     61 */
     62 
     63 #include <cstdio>
     64 #include <cstring>
     65 using namespace std;
     66 
     67 const int maxn = 100 + 5;
     68 int n, m, k;
     69 int linkery[maxn], linkerx[maxn];
     70 bool used[maxn], g[maxn][maxn];
     71 bool flag;
     72 
     73 bool dfs(int u) {
     74     for(int v = 1; v <= m; v ++) {
     75         if(g[u][v] && !used[v]) {
     76             used[v] = true;
     77             if(linkery[v] == -1 || dfs(linkery[v])) {
     78                 if(flag) {
     79                     linkery[v] = u;
     80                     linkerx[u] = v;
     81                 }
     82                 return true;
     83             }
     84         }
     85     }
     86     return false;
     87 }
     88 
     89 int hungary() {
     90     flag = true;
     91     memset(linkery, -1, sizeof linkery);
     92     memset(linkerx, -1, sizeof linkerx);
     93     int res = 0;
     94     for(int i = 1; i <= n; i ++) {
     95         memset(used, false, sizeof used);
     96         if(dfs(i)) res ++;
     97     }
     98     return res;
     99 }
    100 
    101 bool can() {
    102     flag = false;
    103     for(int u = 1; u <= n; u ++) {
    104         if(linkerx[u] == -1) {
    105             memset(used, false, sizeof used);
    106             if(dfs(u)) return true;
    107         }
    108     }
    109     return false;
    110 }
    111 
    112 int main() {
    113     int u, v, Case = 0;
    114     while(~scanf("%d %d %d", &n, &m, &k)) {
    115         memset(g, false, sizeof g);
    116         for(int i = 0; i < k; i ++) {
    117             scanf("%d %d", &u, &v);
    118             g[u][v] = true;
    119         }
    120         int ans = hungary();
    121         int res = 0, temp;
    122         for(int i = 1; i <= n; i ++) {
    123             if(~linkerx[i]) {
    124                 temp = linkerx[i];
    125                 linkerx[i] = linkery[temp] = -1;
    126                 g[i][temp] = false;
    127                 if(!can()) res ++;
    128                 linkerx[i] = temp;
    129                 linkery[temp] = i;
    130                 g[i][temp] = true;
    131             }
    132         }
    133         printf("Board %d have %d important blanks for %d chessmen.
    ", ++ Case, res, ans);
    134     }
    135     return 0;
    136 }
  • 相关阅读:
    关于如何正确地在android项目中添加第三方jar包
    如何在asp.net页面使用css和js
    Prolog 外部不能有 DOCTYPE 声明。处理资源 'http://192.168.115.152:8082/api/EmpApi.aspx' 时出错。第 3 行,位置: 11
    怎样在iis中发布asp.net网站
    WInform 创建一个简单的WPF应用
    细说WPF数据绑定
    WPF控件模板
    DC画线
    第一部分 Mysql的基础
    链表○⇢习题集
  • 原文地址:https://www.cnblogs.com/bianjunting/p/11423276.html
Copyright © 2011-2022 走看看