这题的题意是给你一个矩阵,填空格,使得每个有数字的格子的下方或左边的空格值相加等于这个数字。这题可以用网络流做,我们可以建立源点到列值的边,和行值到汇点的边,流量设为本身的值减去他对应的空格个数(原因后面会讲),对于每个空格,我们把它对应的每个行值和列值进行建边,边由列值到行值,流量为8,因为题目这里要求的是1到9,如果流量为9的话,就有可能出现0的情况,所以流量要为8.(因为流量是8了,所以我们一开始建立源点到列值的流量需要减去它对应的空格数,因为多一个空格,流量就少了1)。输出的时候答案就是列值到行值通过的流量加1.
#include <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm>
#define maxn 5050000
#define mem(a, b) memset(a, b, sizeof(a))
#define inf (1e8 + 7)
using namespace std;
int heads[20005], sizes, d[20005], num[20005], pre[105][105][2], ans[105][105], que[20005], n, m, nn, sink, source;
bool vis[20005];
char ch[10];
struct node
{
int l, h, x, y;
}nd[20005];
struct edge
{
int u, v, w, next;
}eg[maxn];
void inits()
{
mem(vis, 0);
mem(d, 0);
mem(num, 0);
mem(heads, -1);
mem(pre, -1);
mem(ans, 0);
sizes = 0;
nn = 0;
return;
}
void add(int u, int v, int w)
{
eg[sizes].v = v;
eg[sizes].w = w;
eg[sizes].next = heads[u];
heads[u] = sizes++;
eg[sizes].v = u;
eg[sizes].w = 0;
eg[sizes].next = heads[v];
heads[v] = sizes++;
return;
}
void get(int a, int b)
{
if(ch[0] == '.')
{
pre[a][b][0] = pre[a][b][1] = 0;
return;
}
if(ch[0] != 'X')
{
int tmp = (ch[0] - '0') * 100 + (ch[1] - '0') * 10 + ch[2] - '0';
nd[++nn].l = tmp;
nd[nn].h = -1;
nd[nn].x = a;
nd[nn].y = b;
pre[a][b][0] = nn;
}
if(ch[4] != 'X')
{
int tmp = (ch[4] - '0') * 100 + (ch[5] - '0') * 10 + ch[6] - '0';
nd[++nn].l = -1;
nd[nn].h = tmp;
nd[nn].x = a;
nd[nn].y = b;
pre[a][b][1] = nn;
}
return;
}
void bfs()
{
int head = 0, ta = 0;
mem(vis, 0);
d[sink] = 0;
vis[sink] = 1;
num[0] = 1;
que[head++] = sink;
while(ta != head)
{
int u = que[ta++];
for(int i = heads[u];i != -1;i = eg[i].next)
{
int v = eg[i].v;
if(!vis[v])
{
vis[v] = 1;
d[v] = d[u] + 1;
num[d[v]]++;
que[head++] = v;
}
}
}
return;
}
int dfs(int a, int cos)
{
if(a == sink)
return cos;
int dd, lv = cos, mins = nn + 1;
for(int i = heads[a];i != -1;i = eg[i].next)
{
int v = eg[i].v;
int w = eg[i].w;
if(w)
{
if(d[v] + 1 == d[a])
{
dd = min(w, lv);
dd = dfs(v, dd);
eg[i].w -= dd;
eg[i^1].w += dd;
lv -= dd;
if(d[source] >= nn + 2)
return cos - lv;
if(!lv)
break;
}
mins = min(mins, d[v]);
}
}
if(lv == cos)
{
num[d[a]]--;
if(!num[d[a]])
d[source] = nn + 2;
d[a] = mins + 1;
num[d[a]]++;
}
return cos - lv;
}
void isap()
{
int st = source;
while(d[st] < nn + 2)
dfs(st, inf);
}
void res(int u)
{
for(int i = heads[u];i != -1;i = eg[i].next)
{
int v = eg[i].v;
if(nd[v].l != -1&&v != sink)
ans[nd[u].x][nd[v].y] += (eg[i].w + 1);
}
return;
}
int main()
{
sink = 20004;
source = 20003;
while(~scanf("%d%d%*c", &n, &m))
{
inits();
for(int i = 0;i < n;i++)
{
for(int j = 0;j < m;j++)
scanf("%s%*c", ch), get(i, j);
}
for(int i = 1;i <= nn;i++)
{
if(nd[i].l != -1)
{
for(int j = nd[i].x + 1;j < n;j++)
{
if(!pre[j][nd[i].y][0])
{
nd[i].l--;
for(int k = nd[i].y - 1;k >= 0;k--)
{
if(nd[pre[j][k][1]].h != -1&&pre[j][k][1] != -1&&pre[j][k][1])
{
add(i, pre[j][k][1], 8);
nd[pre[j][k][1]].h--;
break;
}
}
}
else
break;
}
add(source, i, nd[i].l);
}
}
for(int i = 1;i <= nn;i++)
if(nd[i].h != -1)
add(i, sink, nd[i].h);
bfs();
isap();
for(int i = 1;i <= nn;i++)
{
if(nd[i].h != -1)
res(i);
}
for(int i = 0;i < n;i++)
{
for(int j = 0;j < m;j++)
{
if(pre[i][j][0] != 0)
printf("_ ");
else
printf("%d ", ans[i][j]);
}
printf("\n");
}
}
return 0;
}