Kakuro Extension HDU - 3338 最大流(WA)

题目链接: Kakuro Extension HDU - 3338

题目大意

一个如图所示的矩阵, 有数字的黑色方块左下角的数字表示从这个方块下面一个方块开始一直到边界或另一个黑色方块所有白色方块的数字和, 黑色方块右上角表示右边所有白色方块的数字和
给所有白色方块填上数字(1-9)

思路

和紫书矩阵解压那题一样, 当时更复杂一些, 同样要把每个白色方块的数字减去1后再处理, 每个黑色方块向其下方的白色方块连边, 容量INF, 每个白色方块向其左边的黑色方块连边, 容量INF, 源点S向每个黑色方块连边, 容量为黑色方块左下角数字减去其下方白色方块数量, 每个黑色方块向汇点T连边, 容量为右上角数字减去其右边白色方块数量, 每个白色方块拆成两个, 之间连一条容量为8的边, 求S-T最大流, 然后每个白色方块两个顶点间的流量+1就是白块的数字

一直WA找不出BUG, 以后再写吧

代码(WA)

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <queue>
#include <vector>
#include <map>

using namespace std;

const int MAXV = 100000, INF = 0X3F3F3F3F;
struct edge
{
    int to, cap, rev;
    edge(int a, int b, int c) :to(a), cap(b), rev(c){}
};
vector<edge> G[MAXV];
int iter[MAXV], level[MAXV], S, T;

void add_edge(int from, int to, int cap)
{
    G[from].push_back(edge(to, cap, G[to].size()));
    G[to].push_back(edge(from, 0, G[from].size()-1));
}
bool bfs()
{
    memset(level, -1, sizeof(level));
    level[S] = 0;
    queue<int> que;
    que.push(S);
    while(!que.empty())
    {
        int v = que.front(); que.pop();
        for(int i=0; i<(int)G[v].size(); ++i)
        {
            edge &e = G[v][i];
            if(e.cap>0 && level[e.to]==-1)
            {
                level[e.to] = level[v] + 1;
                que.push(e.to);
            }
        }
    }
    return level[T]!=-1;
}
int dfs(int v, int f)
{
    if(v == T) return f;
    for(int &i=iter[v]; i<(int)G[v].size(); ++i)
    {
        edge &e = G[v][i];
        if(e.cap>0 && level[e.to]>level[v])
        {
            int d = dfs(e.to, min(f, e.cap));
            if(d)
            {
                e.cap -= d;
                G[e.to][e.rev].cap+= d;
                return d;
            }
        }
    }
    return 0;
}

int max_flow()
{
    int flow = 0;
    while(bfs())
    {
        memset(iter, 0, sizeof(iter));
        int f;
        while((f=dfs(S, INF))) flow += f;
    }
    return flow;
}

void init()
{
    for(int i=0; i<MAXV; ++i) G[i].clear();
}

const int MAXN = 500;
int n, m;
struct P
{
    int d, r, id1, id2;
    void in()
    {
        id1 = id2 = -1;
        char s[10];
        scanf("%s", s);
        for(int i=0; s[i]!='\0'; ++i)
            if(s[i] == 'X') s[i] = '1';
            else if(s[i] == '.') s[i] = '0';
        s[3] = ' ';
        sscanf(s, "%d%d", &d, &r);
        if(d == 111) d = -1;
        if(r == 111) r = -1;
    }
};
P p[MAXN][MAXN];



int main()
{
    while(scanf("%d%d", &n, &m) == 2)
    {
        init();
        for(int i=0; i<n; ++i)
            for(int j=0; j<m; ++j) p[i][j].in();
        int cnt = 0;
        S = cnt++;
        T = cnt++;
        for(int i=0; i<n; ++i)
        {
            for(int j=0; j<m; ++j)
            {
                if(p[i][j].r > 0)
                {
                    if(p[i][j].id1 == -1) p[i][j].id1 = cnt++;
                    for(int k=j+1; p[i][k].d==0 && p[i][k].r==0 && k<m; ++k)
                    {
                        if(p[i][k].id1 == -1) p[i][k].id1 = cnt++;
                        add_edge(p[i][j].id1, p[i][k].id1, INF);
                        p[i][j].r--;
                    }
                    add_edge(S, p[i][j].id1, p[i][j].r);
                }
                if(p[i][j].d > 0)
                {
                    if(p[i][j].id2 == -1) p[i][j].id2 = cnt++;
                    for(int k=i+1; p[k][j].d==0&&p[k][j].r==0 && k<n; ++k)
                    {
                        if(p[k][j].id2==-1) p[k][j].id2 =cnt++;
                        add_edge(p[k][j].id2, p[i][j].id2, INF);
                        p[i][j].d--;
                    }
                    add_edge(p[i][j].id2, T, p[i][j].d);
                }
                if(p[i][j].r==0 && p[i][j].d==0)
                {
                    if(p[i][j].id1==-1) p[i][j].id1 = cnt++;
                    if(p[i][j].id2==-1) p[i][j].id2 = cnt++;
                    add_edge(p[i][j].id1, p[i][j].id2, 8);
                }
            }
        }
        max_flow();
        int ans[MAXN][MAXN];
        memset(ans, -1, sizeof(ans));
        for(int i=0; i<n; ++i)
        {
            for(int j=0; j<m; ++j)
            {
                if(p[i][j].r==0 && p[i][j].d==0)
                {
                    int x = p[i][j].id1;
                    int y = p[i][j].id2;
                    for(auto &e: G[x])
                    {
                        if(e.to == y)
                        {
                            ans[i][j] = 8-abs(e.cap)+1;
                        }
                    }
                }
            }
        }
        for(int i=0; i<n; ++i)
        {
            for(int j=0; j<m; ++j)
                if(ans[i][j]==-1) printf("_%c", j==m-1?'\n':' ');
                else printf("%d%c", ans[i][j], j==m-1?'\n':' ');
        }
    }

    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值