【TCO2013 Semifinal 2】 OneBlack

来源:互联网 发布:linux 限制某ip访问 编辑:程序博客网 时间:2024/05/03 12:37

Description

一个  的网格图,一些格子有障碍。一条合法路径的定义是从  到 的,一共走  步的路径。
你要把一些格子染黑,使得每一条合法路径上恰好有一个黑点。问合法方案数。

Difficulty

MainAlgorithm

对偶图
DP

Complexity

Solution

首先我们把能从  到的、能到  的点抠出来。其余的点都是自由的,给答案乘  即可。
我们观察这些点,他们构成了一个平面图DAG。
考虑一下染色的意义,即一个极小点割。即这个割集中的每一个点都有用而不可删除。
那么,我们把原图转对偶图,在左下角建立S,在右上角建立T,一个合法的方案即为从S到T的一条路径。

DP统计一下就好。

#include <iostream>#include <cstdio>#include <algorithm>#include <cstring>#include <cmath>#define Rep(i, x, y) for (int i = x; i <= y; i ++)#define Dwn(i, x, y) for (int i = x; i >= y; i --)#define RepE(i, x) for(int i = pos[x]; i; i = g[i].nex)using namespace std;typedef long long LL;const int N = 1005, M = 45, S = 1001, T = 1002, mod = 1000000007;class OneBlack {public:char a[N][N]; bool vis[M][M], v1[M][M], v2[M][M], ve[N][N], Ch[M][M];LL f[N], num = 1; int in[N], n, m, pos[N], sz, hd, tl, que[N], c[M][M], col, cl, b[N][N];struct Edge { int y, nex; } g[N * N];void Init(int x, int y) {if (x == y || ve[x][y]) return ;g[++ sz] = (Edge) { y, pos[x] }, pos[x] = sz;in[y] ++, ve[x][y] = 1;}void Find(int x, int y) {if (x > n || y > m || vis[x][y] || c[x][y]) return ;c[x][y] = col;Find(x + 1, y), Find(x, y + 1), Find(x + 1, y + 1);}void Dfs(int x, int y) {if (!x || y > m) col = S;if (x > n || !y) col = T;if (col == S || col == T || vis[x][y] || Ch[x][y]) return ;Ch[x][y] = 1;Dfs(x + 1, y), Dfs(x - 1, y), Dfs(x, y - 1), Dfs(x, y + 1);}int countColorings(vector <string> grid) {n = grid.size();m = grid[0].size();Rep(i, 1, n) {Rep(j, 1, m) a[i][j] = grid[i - 1][j - 1];}v1[1][0] = 1, v2[n + 1][m] = 1;Rep(i, 1, n) {Rep(j, 1, m) if (a[i][j] != '#') {v1[i][j] = v1[i - 1][j] | v1[i][j - 1];vis[i][j] = v1[i][j];}}Dwn(i, n, 1) {Dwn(j, m, 1) if (a[i][j] != '#') {v2[i][j] = v2[i + 1][j] | v2[i][j + 1];vis[i][j] &= v2[i][j];}}Rep(i, 1, n) {Rep(j, 1, m) if (a[i][j] != '#' && !vis[i][j]) (num *= 2) %= mod;}Rep(i, 1, n) {Rep(j, 1, m) {if (!c[i][j] && !vis[i][j]) col = (++ cl), Dfs(i, j), Find(i, j);else if (!c[i][j]) b[i][j] = ++ cl;}}Rep(i, 1, n) c[i][0] = T, c[i][m + 1] = S;Rep(i, 1, m) c[0][i] = S, c[n + 1][i] = T;Rep(i, 1, n) {Rep(j, 1, m) {int x = c[i][j];if (!x) {x = b[i][j];if (c[i + 1][j]) Init(x, c[i + 1][j]);if (c[i][j - 1]) Init(x, c[i][j - 1]);if (!c[i + 1][j] && !c[i][j - 1]) Init(x, max(b[i + 1][j - 1], c[i + 1][j - 1]));} else {if (b[i + 1][j]) Init(x, b[i + 1][j]);if (b[i][j - 1]) Init(x, b[i][j - 1]);if (b[i + 1][j - 1]) Init(x, b[i + 1][j - 1]);}if (c[i - 1][j] == S || c[i][j + 1] == S || c[i - 1][j + 1] == S) Init(S, x);}}f[S] = 1, que[hd = tl = 1] = S;while (hd <= tl) {int x = que[hd ++];RepE(i, x) {int y = g[i].y;(f[y] += f[x]) %= mod, in[y] --;if (!in[y]) que[++ tl] = y;}}return int(f[T] * num % mod);}};


0 0
原创粉丝点击