[国家集训队]部落战争 网络流

题面

[国家集训队]部落战争

题解

貌似是一道最小路径覆盖的板子题……
不会的就学学吧,网络流经典建模之一。
不过因为是二分图,所以也可以用匈牙利。
这里的代码是匈牙利的写法,很短。

#include<bits/stdc++.h>
using namespace std;
#define R register int
#define AC 7000
#define ac 800000
#define id(i, j) ((i - 1) * m + j)

int n, m, l, r, ans;
int link[AC];
int Head[AC], date[ac], Next[ac], tot;
char s[60][60];
bool vis[AC];

inline void add(int f, int w)
{
    date[++ tot] = w, Next[tot] = Head[f], Head[f] = tot; 
    //date[++ tot] = f, Next[tot] = Head[w], Head[w] = tot;
    //printf("%d ---> %d
", f, w);
}

void pre()
{
    scanf("%d%d%d%d", &n, &m, &l, &r);
    for(R i = 1; i <= n; i ++) scanf("%s", s[i] + 1);
    int a[10] = {l, l, r, r}, b[5] = {r, -r, l, -l};
    for(R i = 1; i <= n; i ++)
        for(R j = 1; j <= m; j ++) 
        {
            if(s[i][j] == 'x') continue;
            ++ ans;
            for(R k = 0; k < 4; k ++)
            {
                int x = i + a[k], y = j + b[k];
                if(x <= 0 || x > n || y <= 0 || y > m || s[x][y] == 'x') continue;			
                add(id(i, j), id(x, y));
            }
        }
}

bool dfs(int x)
{
    for(R i = Head[x]; i; i = Next[i])
    {
        int now = date[i];
        if(vis[now]) continue;
        vis[now] = true;
        if(!link[now] || dfs(link[now])) {link[now] = x; return true;}
    }
    return false;
}

void work()
{
    for(R i = 1; i <= n * m; i ++)
    {
        memset(vis, 0, sizeof(vis));
        if(dfs(i)) -- ans;
    }
    printf("%d
", ans);
}

int main()
{
//	freopen("in.in", "r", stdin);
    pre();
    work();
//	fclose(stdin);
    return 0;
}
原文地址:https://www.cnblogs.com/ww3113306/p/10474357.html