zoukankan      html  css  js  c++  java
  • P2774 方格取数问题 题解

    题目描述

    我总感觉他这个题面描述怪怪的,总之,讲了这样一件事情

    从一个(N imes M)的矩阵中取点,取每个点时周边的四个点不能取,求取出点的最大值

    P2774 方格取数问题

    问题解决

    显然我们可以对矩阵黑白染色,同为黑色的点为一个阵营,白色为一个阵营,同一个阵营中的点没有任何影响,不同阵营中的点可以会有牵制

    我们反过来考虑牵制

    然后就得到了一个类似二分图的东西,考虑一种数据结构,能删掉一个元素,表示不取这个方格,删掉的代价为方格的权值;要么删掉的总是保证策略最优的,要么能反悔;最终状态为:没有互斥的方格了。

    自然而然就想到了割

    将一个阵营向超级原点建边,另外一个阵营向超级汇点建边,牵制表示建流量为(INF)的边,然后刷最小割(=)最大流就好了

    代码实现

    #include <cstdio>
    #include <cctype>
    #include <cstring>
    #include <queue>
    #define N 10010
    #define E 100010
    #define S 0
    #define T (m * n + 1)
    #define code(i, j) ((i - 1) * m + j)//点的线性标号 
    #define between(x, flo, top) (flo <= x and x <= top)//您是不是不喜欢这个qwq 
    int getint() {
    	int res = 0, ch = getchar();
    	while (!isdigit(ch) and ch != EOF)
    		ch = getchar();
    	while (isdigit(ch))
    		res = res * 10 + (ch - '0'), ch = getchar();
    	return res;
    }
    inline int min(int x, int y) { return (x < y) ? x : y; }
    using std::queue;
    const int d[4][2] = {//待会枚举四个方向用的 
    	{0, 1},
    	{0, -1},
    	{1, 0},
    	{-1, 0}
    };
    
    int m, n;
    int sum = 0;
    
    int first[N];
    int nxt[E], to[E], val[E], cnt = 1;
    void addE(int u, int v, int w) {
    	++cnt;
    	to[cnt] = v;
    	val[cnt] = w;
    	nxt[cnt] = first[u];
    	first[u] = cnt;
    }
    
    int dep[N];
    queue<int> q;
    bool bfs() {
    	memset(dep, 0, sizeof(dep));
    	
    	dep[S] = 1;
    	q.push(S);
    	while (not q.empty()) {
    		int u = q.front();
    		q.pop();
    		for (int p = first[u]; p; p = nxt[p]) {
    			int v = to[p];
    			if (dep[v])
    				continue;
    			if (val[p]) {//放心,开始都是正权的情况下,不会出现负数的 
    				dep[v] = dep[u] + 1;
    				q.push(v);
    			}
    		}
    	}
    	return dep[T];
    }
    
    int dfs(int u, int in) {
    	if (u == T)
    		return in;
    	int out = 0;
    	for (int p = first[u]; p and in; p = nxt[p]) {
    		
    		if (val[p] == 0)
    			continue;
    		int v = to[p];
    		if (dep[v] != dep[u] + 1)
    			continue;
    		
    		int res = dfs(v, min(val[p], in));
    		val[p] -= res;
    		val[p ^ 1] += res;
    		in -= res;
    		out += res;
    	}
    	
    	return out;
    }
    
    int main() {
    	n = getint(), m = getint();
    	for (int i = 1; i <= n; ++i)
    		for (int j = 1; j <= m; ++j) {
    			int w = 0;
    			sum += w = getint();//假定全部都取,随后会删 
    			if ((i + j) % 2 == 0) {//阵营A,源点连向自己,自己连向阵营B 
    				addE(S, code(i, j), w);
    				addE(code(i, j), S, 0);
    				
    				for (int k = 0; k <= 3; ++k) {
    					int x = i + d[k][0], y = j + d[k][1];
    					if (between(x, 1, n) and between(y, 1, m)) {
    						addE(code(i, j), code(x, y), 2e9);
    						addE(code(x, y), code(i, j), 0);
    					}
    				}				
    			}
    			else {//阵营B,连向汇点 
    				addE(code(i, j), T, w);
    				addE(T, code(i, j), 0);
    			}
    		}
    	
    	int cut = 0;//最小割 
    	while (bfs())
    		cut += dfs(S, 2e9);//最小割 = 最大流 
    	printf("%d
    ", sum - cut);
    	return 0;
    }
    
  • 相关阅读:
    使用 libevent 和 libev 提高网络应用性能
    An existing connection was forcibly closed by the remote host
    各种浏览器的兼容css
    vs输出窗口,显示build的时间
    sass
    网站设置404错误页
    List of content management systems
    css footer not displaying at the bottom of the page
    强制刷新css
    sp_executesql invalid object name
  • 原文地址:https://www.cnblogs.com/martian148/p/15185140.html
Copyright © 2011-2022 走看看