HDU - 3338 Kakuro Extension(最大流)

题目大意:看一下图基本就知道了

解题思路:难点是构图。。

设置一个超级源点和所有的行的和相连,容量为该行的和 - 该行和由几个数相加得到

设置一个超级汇点,和所有列的和相连,容量为该列的和 - 该列和由几个数相加得到

接着就是空白部分和 “行和“和 “列和“的关系了

空白连向该行的行和,权值为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 0x3f3f3f3f

struct 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 110

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

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-08-02 01:09:37

HDU - 3338 Kakuro Extension(最大流)的相关文章

hdu 3338 Kakuro Extension(最大流)

hdu 3338 Kakuro Extension Description If you solved problem like this, forget it.Because you need to use a completely different algorithm to solve the following one. Kakuro puzzle is played on a grid of "black" and "white" cells. Apart

HDU 3338 Kakuro Extension(网络流)

HDU 3338 Kakuro Extension 题目链接 题意:完成如图的游戏,填充数字1-9 思路:网络流的行列模型,把每行每列连续的一段拆分出来建图即可,然后题目有限制一个下限1,所以 每行每列的容量减去相应的数字,然后建图建容量8就好,这样就默认原来容量已经有1了 代码: #include <cstdio> #include <cstring> #include <queue> #include <algorithm> using namespac

HDU 3338 Kakuro Extension

网络最大流 TLE了两天的题目.80次Submit才AC,发现是刘汝佳白书的Dinic代码还可以优化.....瞬间无语..... #include<cstdio> #include<cstring> #include<string> #include<cmath> #include<vector> #include<queue> #include<algorithm> using namespace std; const

hdoj 3338 Kakuro Extension 【经典最大流+输出流量】

题目:hdoj 3338 Kakuro Extension 定义:神级最大流(各种错误无数次,整整一天) 题意:一个游戏,这个游戏给出一个矩阵,有些矩阵里面有两个数,前面一个数表示从下一行到下一个出现数字行的所有数字和(当前这一列),而第二个数表示从下一列到下一个出现数字的列(当前这一行),让你填入满足条件的数字的矩阵(1---9),可以重复(最大流条件). 分析:首先数字可以重复那么确定了可以用最大流来做,建图方法就是列进行出,或者行进列出,前者比较好写. 这个题目还有一个条件就是要求必须有流

HDU-3338 Kakuro Extension(最大流,方格横纵和问题)

题目链接:HDU-3338 Kakuro Extension 题意 给出一个$n\times m$的网格,每个格子为黑色或白色,对于一行中连续的若干个白色格子,我们要往这若干个白色格子中填入$1\sim 9$的数字,使其和等于左边黑色格子中的一个已知数字$a_1$:对于一列中连续的若干个白色格子,同理填入$1\sim 9$的数字使其和等于上边黑色格子中的一个已知数字$a_2$.如果一个黑色格子相邻的右边和下边都有白色格子,那么这个黑色格子是带有两个已知数字$a_1$和$a_2$的,分别代表右边和

hdu 3344 Kakuro Extension Extension

Kakuro Extension Extension Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 468    Accepted Submission(s): 240 Problem Description You know ,I'm a lazy guy and write problem description is a ver

HDU3338 Kakuro Extension(最大流+思维构图)

这道题一定要写一下,卡了好久. 题意: 有黑白两种方格,最上边一行和最左边一列一定是黑色,然后其余的地方有可能是黑色,有可能是白色,和白色相邻的黑色方格里有数字(1个或2个), 现在要求在白色方格里填1~9中的一个数字,使得一个黑色方格下边的数字 = sigma(该黑色方格下边白色方格数字)  这个sigma不是下边全部的白方格, 而是一直往下走一直走到一个黑方格之前所有的白方格,详情见样例1.相同的,黑方格右上角的数字 = sigma(该黑色方格右边白色方格数字). 思路: 可以很容易看出,所

hdu 3338 最大流 ****

题意: 黑格子右上代表该行的和,左下代表该列下的和 链接:点我 这题可以用网络流做.以空白格为节点,假设流是从左流入,从上流出的,流入的容量为行和,流出来容量为列和,其余容量不变.求满足的最大流.由于流量有上下限限制,可以给每个数都减掉1,则填出来的数字范围为0—8, 就可以用单纯的网络流搞定了.求出来再加上就可以了. 这一题主要是在建图 建图: 一共有四类点: 1. 构造源点ST,汇点ED 2. 有行和的格子,即\上面有值的格子,此类节点设为A 3. 空白格,设为B 4. 有列和的格子,即\下

Kakuro Extension (hdu 3338 最大流 建图难)

Kakuro Extension Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 1093    Accepted Submission(s): 377 Special Judge Problem Description If you solved problem like this, forget it.Because you nee