HDU3338 Kakuro Extension 网络流 isap

来源:互联网 发布:陈奕迅歌词 知乎 编辑:程序博客网 时间:2024/06/06 10:05
  这题的题意是给你一个矩阵,填空格,使得每个有数字的格子的下方或左边的空格值相加等于这个数字。这题可以用网络流做,我们可以建立源点到列值的边,和行值到汇点的边,流量设为本身的值减去他对应的空格个数(原因后面会讲),对于每个空格,我们把它对应的每个行值和列值进行建边,边由列值到行值,流量为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;}

0 0
原创粉丝点击