码迷,mamicode.com
首页 > 其他好文 > 详细

P2774 方格取数问题

时间:2018-12-16 17:11:04      阅读:152      评论:0      收藏:0      [点我收藏+]

标签:main   for   问题   bool   include   clu   str   输出   cpp   

\(\color{#0066ff}{题目描述}\)

在一个有 m*n 个方格的棋盘中,每个方格中有一个正整数。现要从方格中取数,使任意 2 个数所在方格没有公共边,且取出的数的总和最大。试设计一个满足要求的取数算法。对于给定的方格棋盘,按照取数要求编程找出总和最大的数。

\(\color{#0066ff}{输入格式}\)

第 1 行有 2 个正整数 m 和 n,分别表示棋盘的行数和列数。接下来的 m 行,每行有 n 个正整数,表示棋盘方格中的数。

\(\color{#0066ff}{输出格式}\)

程序运行结束时,将取数的最大总和输出

\(\color{#0066ff}{输入样例}\)

3 3
1 2 3
3 2 3
2 3 1 

\(\color{#0066ff}{输出样例}\)

11

\(\color{#0066ff}{数据范围与提示}\)

m,n<=100

\(\color{#0066ff}{题解}\)

最小割 = 最大流

通过把每个点横纵坐标相加的奇偶性,分为奇点和偶点

可以发现,奇点之间互不影响,偶点同理

S向所有奇点连边,所有偶点向T连边

奇点向相邻偶点连边

跑最大流(最小割)

最后用总数减就行了

#include <bits/stdc++.h>
#define LL long long
inline LL in() {
    char ch; LL x = 0, f = 1;
    while(!isdigit(ch = getchar()))(ch == '-') && (f = -f);
    while(isdigit(ch)) x = (x << 1) + (x << 3) + (ch ^ 48), ch = getchar();
    return x * f;
}
const int max = 105050;
const int inf = 0x7fffffff;
struct node {
    int to, dis;
    node *nxt, *lst;
    node(int to = 0, int dis = 0, node *nxt = NULL):to(to), dis(dis), nxt(nxt) {}
    void *operator new (size_t) {
        static node *S = NULL, *T = NULL;
        return (S == T) && (T = (S = new node[1024]) + 1024), S++;
    }
};
int rx[] = {0, 0, -1, 1};
int ry[] = {1, -1, 0, 0};
typedef node* nod;
nod head[max], cur[max];
int dep[max];
int id[120][120], mp[120][120];
std::queue<int> q;
int n, m, s, t;
int ans;
inline void add(int from, int to, int dis) {
    nod o = new node(to, dis, head[from]);
    head[from] = o;
}
inline void link(int from, int to, int dis) {
    add(from, to, dis);
    add(to, from, 0);
    head[from]->lst = head[to];
    head[to]->lst = head[from];
}
inline bool bfs() {
    for(int i = s; i <= t; i++) dep[i] = 0, cur[i] = head[i];
    dep[s] = 1;
    q.push(s);
    while(!q.empty()) {
        int tp = q.front(); q.pop();
        for(nod i = head[tp]; i; i = i->nxt) {
            if(!dep[i->to] && i->dis > 0 ) {
                dep[i->to] = dep[tp] + 1;
                q.push(i->to);
            }
        }
    }
    return dep[t];
}
inline int dfs(int x, int change) {
    if(x == t || !change) return change;
    int flow = 0, ls;
    for(nod i = head[x]; i; i = i->nxt) {
        cur[x] = i;
        if(dep[i->to] == dep[x] + 1 && (ls = dfs(i->to, std::min(change, i->dis)))) {
            flow += ls;
            change -= ls;
            i->dis -= ls;
            i->lst->dis += ls;
            if(!change) break;
        }
    }
    return flow;
}
inline int dinic() {
    int flow = 0;
    while(bfs()) flow += dfs(s, inf);
    return flow;
}
int main() {
    n = in(), m = in();
    for(int cnt = 0, i = 1; i <= n; i++) 
        for(int j = 1; j <= m; j++) 
            id[i][j] = ++cnt, ans += (mp[i][j] = in());
    s = 0, t = id[n][m] + 1;
    for(int cnt = 0, i = 1; i <= n; i++)
        for(int j = 1; j <= m; j++) {
            if((i + j) & 1) {
                link(s, id[i][j], mp[i][j]);
                for(int k = 0; k < 4; k++) {
                    int xx = i + rx[k];
                    int yy = j + ry[k];
                    if(xx >= 1 && xx <= n && yy >= 1 && yy <= m)
                        link(id[i][j], id[xx][yy], inf);
                }
            }
            else link(id[i][j], t, mp[i][j]);
        }
    printf("%d", ans - dinic());            
    return 0;
}

P2774 方格取数问题

标签:main   for   问题   bool   include   clu   str   输出   cpp   

原文地址:https://www.cnblogs.com/olinr/p/10127108.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!