zoukankan      html  css  js  c++  java
  • [洛谷P2774]方格取数问题

    题目大意:给你一个$n imes m$的方格,要求你从中选择一些数,其中没有相邻两个数,使得最后和最大

    题解:网络流,最小割,发现相邻的两个点不可以同时选择,进行黑白染色,原点向黑点连一条容量为点权的边,白点向汇点连一条容量为点权的边,黑点向周围一圈的白点连容量为$inf$的边,总权值减去跑出来的最小割就是答案。

    卡点:

    C++ Code:

    #include <algorithm>
    #include <cstdio>
    #include <cctype>
    namespace __IO {
    	namespace R {
    		int x, ch;
    		inline int read() {
    			ch = getchar();
    			while (isspace(ch)) ch = getchar();
    			for (x = ch & 15, ch = getchar(); isdigit(ch); ch = getchar()) x = x * 10 + (ch & 15);
    			return x;
    		}
    	}
    }
    using __IO::R::read;
    
    #define maxn 100010
    #define maxm (maxn << 3)
    const int inf = 0x3f3f3f3f;
    
    int n, m, sum;
    namespace Network_Flow {
    	int st, ed, MF;
    	int head[maxn], cnt = 1;
    	struct Edge {
    		int to, nxt, w;
    	} e[maxm << 1];
    	inline void addedge(int a, int b, int c) {
    		e[++cnt] = (Edge) {b, head[a], c}; head[a] = cnt;
    		e[++cnt] = (Edge) {a, head[b], 0}; head[b] = cnt;
    	}
    	
    	int GAP[maxn], d[maxn], lst[maxn];
    	int q[maxn], h, t;
    	void init() {
    		GAP[d[ed] = 1] = 1;
    		for (int i = st; i <= ed; i++) lst[i] = head[i];
    		q[h = t = 0] = ed;
    		while (h <= t) {
    			int u = q[h++];
    			for (int i = head[u]; i; i = e[i].nxt) {
    				int v = e[i].to;
    				if (!d[v]) {
    					d[v] = d[u] + 1;
    					GAP[d[v]]++;
    					q[++t] = v;
    				}
    			}
    		}
    	}
    	int dfs(int u, int low) {
    		if (!low || u == ed) return low;
    		int w, res = 0;
    		for (int &i = lst[u]; i; i = e[i].nxt) if (e[i].w) {
    			int v = e[i].to;
    			if (d[u] == d[v] + 1) {
    				w = dfs(v, std::min(low, e[i].w));
    				res += w, low -= w;
    				e[i].w -= w, e[i ^ 1].w += w;
    				if (!low) return res;
    			}
    		}
    		if (!(--GAP[d[u]])) d[st] = ed + 1;
    		++GAP[++d[u]], lst[u] = head[u];
    		return res;
    	}
    	void ISAP(int __st, int __ed) {
    		st = __st, ed = __ed;
    		init();
    		while (d[st] <= ed) MF += dfs(st, inf);
    	}
    }
    using Network_Flow::addedge;
    
    inline int get(int x, int y) {return (x - 1) * m + y;}
    const int D[2][4] = {{0, 1, 0, -1}, {1, 0, -1, 0}};
    inline bool over_range(int x, int y) {
    	return x < 1 || x > n || y < 1 || y > m;
    }
    int main() {
    	n = read(), m = read();
    	int st = 0, ed = n * m + 1;
    	for (int i = 1, x, pos; i <= n; i++) {
    		for (int j = 1; j <= m; j++) {
    			sum += x = read(), pos = get(i, j);
    			if (i + j & 1) {
    				addedge(st, pos, x);
    				for (int k = 0; k < 4; k++) {
    					int __x = i + D[0][k], __y = j + D[1][k];
    					if (!over_range(__x, __y)) addedge(pos, get(__x, __y), inf);
    				}
    			} else addedge(pos, ed, x);
    		}
    	}
    	Network_Flow::ISAP(st, ed);
    	printf("%d
    ", sum - Network_Flow::MF);
    	return 0;
    }
    

      

  • 相关阅读:
    arthas命令ognl视频演示
    arthas命令sc和sm视频演示
    混合Java函数和Groovy闭包
    Mock System.in和检查System.out
    arthas命令logger动态修改日志级别--视频演示
    删除List中null的N种方法--最后放大招
    ovs安装教程
    win10中安装与配置maven
    win10系统中按顺序安装jdk、tomcat
    win10系统中按顺序安装jdk、tomcat
  • 原文地址:https://www.cnblogs.com/Memory-of-winter/p/10040708.html
Copyright © 2011-2022 走看看