P2172 [国家集训队]部落战争(最小路径覆盖)

传送门

题目大意:给我们一个矩阵表示村庄,可以在矩阵上放一些骑士,然后骑士可以按照

RxC的格式向下方行进,每个村庄只能被一个骑士占领,问咱们最少需要安放多少骑士。

思路:还是看的题解....网络瘤太难了啊,我好垃圾啊~说是最小路径覆盖模板题...

观察这题,每个骑士走的路线是不是刚好把整个图给覆盖完了,所以这不就是最小路径覆盖

嘛,怎么做呢?我们把每个可以放置骑士的位置拆点,一个与源点连边,一个与汇点连边。

然后找该位置可以向下继续放置的其余点,用入点与其出点连边,

然后跑最大流,每连一条边就可以合并一条路径。

最小路径覆盖=原图的结点数-新图的最大匹配数。

博客传送门

部分代码:

int n, m, r, c;
char str[55][55];
int dx[4];
int dy[4];
int main() {
    //freopen("test.txt", "r", stdin);
    scanf("%d%d%d%d", &m, &n, &r, &c);
    int sum = 0;
    s = n * m*2 + 1, t = s + 1;
    for (int i = 0; i < m; i++) {
        scanf("%s", &str[i]);
    }
    dx[0] = -r, dy[0] = c, dx[1] = -c, dy[1] = r, dx[2] = -r, dy[2] = -c, dx[3] = -c, dy[3] = -r;
    //确定向下的四个方向
    for (int i = 0; i < m; i++) {
        for (int j = 0; j < n; j++) {
            if (str[i][j] == '.') {
                sum++;
                add(s, i * n + j, 1);
                add(m * n + i * n + j, t, 1);//拆点
                for (int d = 0; d < 4; d++) {
                    int tx = i + dx[d];
                    int ty = j + dy[d];
                    if (tx >= 0 && tx < m && ty >= 0 && ty < n && str[tx][ty] == '.') {
                        add(i * n + j, m * n + tx * n + ty,1);//
                    }
                }
            }
        }
    }
    printf("%lld\n", sum - dinic());
    return 0;
}

 

posted @ 2021-04-09 15:04  cono奇犽哒  阅读(65)  评论(0)    收藏  举报