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; }