HDU 1281 - 棋盘游戏 ( 二分图匹配 , 匈牙利算法 )

题意

给出一个N*M (1 < N,M <= 100) 的棋盘,规定只有某些格子可以放“車”。要求放置的“車”不能互相攻击(不在同一行同一列)
在保证尽量多的“車”的前提下,棋盘里有些格子是可以避开的,也就是说,不在这些格子上放车,也可以保证尽量多的“車”被放下。但是某些格子若不放子,就无法保证放尽量多的“車”,这样的格子被称做重要点。求有多少个这样的重要点。

思路

匈牙利算法做二分图匹配。
匈牙利算法(简单易懂)
由于每一行每一列都只有一个“車”,相当于行、列做匹配,让车的数量最多就是相当于求最大匹配数。故先用匈牙利算法板子求出最开始的匹配数。
至于“重要点”,只需要暴力遍历一遍,依次将可以放的格子标记为不可放,每次跑匈牙利,如果匹配数减少了,说明该格子是重要点。

AC代码

#include 
#include 
#include 
#include 
#include 
using namespace std;
const int maxn = 105;
int g[maxn][maxn];
int match[maxn];
bool used[maxn];
struct node{
    int x, y;
}p[maxn*maxn];
int n, m, k;

bool dfs(int v)
{
    for(int j = 1; j <= m; j++){
        if(g[v][j] && !used[j]){
            used[j] = 1;
            if(match[j] == 0 || dfs(match[j]) == 1){
                match[j] = v;
                return true;
            }
        }
    }
    return false;
}

int hungary()
{
    int res = 0;
    memset(match, 0, sizeof match);
    for(int v = 1; v <= n; v++){
        memset(used, 0, sizeof used);
        if(dfs(v)) res++;
    }
    return res;
}

int main()
{
    int kase = 0;
    while( ~scanf("%d%d%d",&n,&m,&k) ){
        memset(g, 0, sizeof g);
        for(int i = 0; i < k; i++){
            scanf("%d%d",&p[i].x,&p[i].y);
            g[p[i].x][p[i].y] = 1;
        }
        int h = hungary();
        int ans = 0;
        for(int i = 0; i < k; i++){
            g[p[i].x][p[i].y] = 0;
            if(hungary() < h) ans++;
            g[p[i].x][p[i].y] = 1;
        }
        printf("Board %d have %d important blanks for %d chessmen.\n", ++kase, ans, h);
    }
    return 0;
}

你可能感兴趣的:(网络流)