標籤:
題目大意:看一基本就知道了
解題思路:痛點是構圖。。
設定一個超級源點和所有的行的和相連,容量為該行的和 - 該行和由幾個數相加得到
設定一個超級匯點,和所有列的和相連,容量為該列的和 - 該列和由幾個數相加得到
接著就是空白部分和 “行和“和 “列和“的關係了
空白連向該行的行和,權值為8
空白連向該列的列和,權值也為8
為什麼為8,而不是9,因為流量也可能為0,但是0是不能填的,所以將容量設為8,最後取值的時候加1即可
#include <cstdio>#include <cstring>#include <algorithm>#include <vector>#include <queue>using namespace std;#define N 100010#define INF 0x3f3f3f3fstruct Edge { int from, to, cap, flow; Edge() {} Edge(int from, int to, int cap, int flow): from(from), to(to), cap(cap), flow(flow) {}};struct ISAP { int p[N], num[N], cur[N], d[N]; int t, s, n, m; bool vis[N]; vector<int> G[N]; vector<Edge> edges; void init(int n) { this->n = n; for (int i = 0; i <= n; i++) { G[i].clear(); d[i] = INF; } edges.clear(); } void AddEdge(int from, int to, int cap) { edges.push_back(Edge(from, to, cap, 0)); edges.push_back(Edge(to, from, 0, 0)); m = edges.size(); G[from].push_back(m - 2); G[to].push_back(m - 1); } bool BFS() { memset(vis, 0, sizeof(vis)); queue<int> Q; d[t] = 0; vis[t] = 1; Q.push(t); while (!Q.empty()) { int u = Q.front(); Q.pop(); for (int i = 0; i < G[u].size(); i++) { Edge &e = edges[G[u][i] ^ 1]; if (!vis[e.from] && e.cap > e.flow) { vis[e.from] = true; d[e.from] = d[u] + 1; Q.push(e.from); } } } return vis[s]; } int Augment() { int u = t, flow = INF; while (u != s) { Edge &e = edges[p[u]]; flow = min(flow, e.cap - e.flow); u = edges[p[u]].from; } u = t; while (u != s) { edges[p[u]].flow += flow; edges[p[u] ^ 1].flow -= flow; u = edges[p[u]].from; } return flow; } int Maxflow(int s, int t) { this->s = s; this->t = t; int flow = 0; BFS(); if (d[s] > n) return 0; memset(num, 0, sizeof(num)); memset(cur, 0, sizeof(cur)); for (int i = 0; i < n; i++) if (d[i] < INF) num[d[i]]++; int u = s; while (d[s] <= n) { if (u == t) { flow += Augment(); u = s; } bool ok = false; for (int i = cur[u]; i < G[u].size(); i++) { Edge &e = edges[G[u][i]]; if (e.cap > e.flow && d[u] == d[e.to] + 1) { ok = true; p[e.to] = G[u][i]; cur[u] = i; u = e.to; break; } } if (!ok) { int Min = n; for (int i = 0; i < G[u].size(); i++) { Edge &e = edges[G[u][i]]; if (e.cap > e.flow) Min = min(Min, d[e.to]); } if (--num[d[u]] == 0) break; num[d[u] = Min + 1]++; cur[u] = 0; if (u != s) u = edges[p[u]].from; } } return flow; }};ISAP isap;#define M 110struct Node { int row, col, val; Node() {} Node(int row, int col, int val): row(row), col(col), val(val){}}row[N], col[N];int n, m;int empty[M][M];char map[M];void solve() { int cnt_row = 0, cnt_col = 0, cnt_empty = 0; memset(empty, 0, sizeof(empty)); for (int i = 1; i <= n; i++) for (int j = 1; j <= m; j++) { scanf("%s", map); if (strcmp(map, ".......") == 0) empty[i][j] = ++cnt_empty; else if(map[3] == ‘\\‘) { int t; if (map[0] != ‘X‘) { t = (map[0] - ‘0‘) * 100 + (map[1] - ‘0‘) * 10 + (map[2] - ‘0‘); col[++cnt_col] = Node(i, j, t); } if (map[4] != ‘X‘) { t = (map[4] - ‘0‘) * 100 + (map[5] - ‘0‘) * 10 + (map[6] - ‘0‘); row[++cnt_row] = Node(i, j, t); } } } int s = 0, t = cnt_empty + cnt_row + cnt_col + 1; isap.init(t); for (int i = 1; i <= cnt_row; i++) { int x = row[i].row; int cnt = 0; for (int y = row[i].col + 1; y <= m; y++) { if(empty[x][y]) { cnt++; isap.AddEdge(i, cnt_row + empty[x][y], 8); } else break; } isap.AddEdge(s, i, row[i].val - cnt); } for (int i = 1; i <= cnt_col; i++) { int y = col[i].col; int cnt = 0; for (int x = col[i].row + 1; x <= n; x++) { if (empty[x][y]) { cnt++; isap.AddEdge(cnt_row + empty[x][y], cnt_row + cnt_empty + i, 8); } else break; } isap.AddEdge(cnt_row + cnt_empty + i, t, col[i].val - cnt); } isap.Maxflow(s, t); for (int i = 1; i <= n; i++) { for (int j = 1; j <= m; j++) { if (empty[i][j]) { int ans = 0; for (int k = 0; k < isap.G[empty[i][j] + cnt_row].size(); k++) { Edge &e = isap.edges[isap.G[empty[i][j] + cnt_row][k]]; if (e.to > cnt_row + cnt_empty) { ans += e.flow; break; } } printf("%d ", ans + 1); } else printf("_ "); } printf("\n"); }}int main() { while (scanf("%d%d", &n, &m) != EOF) { solve(); } return 0;}
著作權聲明:本文為博主原創文章,未經博主允許不得轉載。
HDU - 3338 Kakuro Extension(最大流)