Kakuro Extension最大流

Posted wuliwuliiii

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Kakuro Extension最大流相关的知识,希望对你有一定的参考价值。

HDU-3338

  这道题真的处理起来好复杂啊,题意就是个简单的方格填数问题,但是每个白点至少放1,那么最后的可能解是怎样的呢?我们是不是要把x轴上的和y轴上的统一起来,然后就是每个点都被对应的x和y匹配起来,那么,之后,用每个点的x向y建立边,跑最大流,每个点的放的值就是反向边的权值了。

 

#include <iostream>
#include <cstdio>
#include <cmath>
#include <string>
#include <cstring>
#include <algorithm>
#include <limits>
#include <vector>
#include <stack>
#include <queue>
#include <set>
#include <map>
#define lowbit(x) ( x&(-x) )
#define pi 3.141592653589793
#define e 2.718281828459045
#define INF 0x3f3f3f3f
#define HalF (l + r)>>1
#define lsn rt<<1
#define rsn rt<<1|1
#define Lson lsn, l, mid
#define Rson rsn, mid+1, r
#define QL Lson, ql, qr
#define QR Rson, ql, qr
#define myself rt, l, r
#define MP(x, y) make_pair(x, y)
using namespace std;
typedef unsigned long long ull;
typedef long long ll;
const int maxN = 1e2 + 7, maxE = 1e5 + 7, st = 0;
pair<int, int> re_xy[20007];
int N, M, head[20007], cur[20007], cnt, ed, id[maxN][maxN], tot, ou[maxN][maxN];
char mp[maxN][maxN][10];
int down[maxN][maxN], righ[maxN][maxN];
struct Eddge

    int nex, to, flow;
    Eddge(int a=-1, int b=0, int c=0):nex(a), to(b), flow(c) 
edge[maxE];
inline void addEddge(int u, int v, int w)

    edge[cnt] = Eddge(head[u], v, w);
    head[u] = cnt++;

inline void _add(int u, int v, int w)  addEddge(u, v, w); addEddge(v, u, 0); 
inline void solve(int x, int y)

    if(mp[x][y][1] == X && mp[x][y][7] == X)  id[x][y] = -1; return; 
    if(mp[x][y][1] == .)  return; 
    re_xy[++tot] = MP(x, y);
    id[x][y] = tot;
    down[x][y] = righ[x][y] = 0;
    if(mp[x][y][1] != X) for(int i=1; i<=3; i++) down[x][y] = down[x][y] * 10 + mp[x][y][i] - 0;
    if(mp[x][y][5] != X) for(int i=5; i<=7; i++) righ[x][y] = righ[x][y] * 10 + mp[x][y][i] - 0;

int deep[20007];
queue<int> Q;
inline bool bfs()

    for(int i=0; i<=ed; i++) deep[i] = 0;
    deep[st] = 1;
    while(!Q.empty()) Q.pop();
    Q.push(st);
    while(!Q.empty())
    
        int u = Q.front(); Q.pop();
        for(int i=head[u], v, f; ~i; i=edge[i].nex)
        
            v = edge[i].to; f = edge[i].flow;
            if(f && !deep[v])
            
                deep[v] = deep[u] + 1;
                Q.push(v);
            
        
    
    return deep[ed];

int  dfs(int u, int Dist)

    if(u == ed) return Dist;
    for(int &i=cur[u], v, f; ~i; i=edge[i].nex)
    
        v = edge[i].to; f = edge[i].flow;
        if(f && deep[v] == deep[u] + 1)
        
            int di = dfs(v, min(Dist, f));
            if(di)
            
                edge[i].flow -= di;
                edge[i^1].flow += di;
                return di;
            
        
    
    return 0;

inline int Dinic()

    int ans = 0, tmp;
    while(bfs())
    
        for(int i=0; i<=ed; i++) cur[i] = head[i];
        while((tmp = dfs(st, INF))) ans += tmp;
    
    return ans;

inline void init()

    cnt = tot = 0;
    memset(head, -1, sizeof(head));
    memset(id, 0, sizeof(id));

int main()

    while(scanf("%d%d", &N, &M) != EOF)
    
        init();
        for(int i=1; i<=N; i++)
        
            for(int j=1; j<=M; j++)
            
                scanf("%s", mp[i][j] + 1);
                solve(i, j);
            
        
        ed = (tot << 1) + 1;
        for(int i=1, le_id=0, up_id=0; i<=N; i++)
        
            for(int j=1; j<=M; j++)
            
                if(mp[i][j][1] == .)
                
                    for(int dx = i - 1; dx > 0; dx--)
                    
                        if(id[dx][j])
                        
                            up_id = dx;
                            down[dx][j]--;
                            break;
                        
                    
                    for(int dy = j - 1; dy > 0; dy--)
                    
                        if(id[i][dy])
                        
                            le_id = dy;
                            righ[i][dy]--;
                            break;
                        
                    
                    _add(id[i][le_id], id[up_id][j] + tot, 8);
                
            
        
        for(int i=1; i<=N; i++)
        
            for(int j=1; j<=M; j++)
            
                if(id[i][j] > 0)
                
                    if(mp[i][j][1] != X) _add(id[i][j] + tot, ed, down[i][j]);
                    if(mp[i][j][5] != X) _add(st, id[i][j], righ[i][j]);
                
            
        
        Dinic();
        for(int x = 1; x <= tot; x++)
        
            for(int i=head[x], y, f; ~i; i=edge[i].nex)
            
                y = edge[i].to; f = edge[i^1].flow;
                if(y == st) continue;
                ou[re_xy[x].first][re_xy[y - tot].second] = f;
            
        
        for(int i=1; i<=N; i++)
        
            for(int j=1; j<=M; j++)
            
                if(mp[i][j][1] != .) printf("_");
                else printf("%d", ou[i][j] + 1);
                printf("%c", j == M ? \n :  );
            
        
    
    return 0;

/*
3 3
XXXXXXX 009/XXX XXXXXXX
XXX/009 ....... XXXXXXX
XXXXXXX XXXXXXX XXXXXXX
*/

 

 

 

以上是关于Kakuro Extension最大流的主要内容,如果未能解决你的问题,请参考以下文章

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

网络流--最小费用最大流 (理解)

最小费用最大流问题

最大流问题

网络最大流学习随笔,详解网络流最大流

最小费用最大流模板