zoukankan      html  css  js  c++  java
  • [BZOJ 3774] 最优选择 【最小割】

    题目链接:BZOJ - 3774

    题目分析

    此题与“文理分科”那道题目有些类似。都是使用最小割来求解,先加上可能获得的权值,在减掉必须舍弃的权值(最小割)。

    文理分科是规定每个人和 S 连就是选文,和 T 连就是选理。然后如果一个人和相邻的人都全文就会获得一个权值,那么我们就为这个权值建一个点,让这个点与必须同时选文的5个人连 INF 边。这样只要这 5 个人中有一个人选了理,就必须舍弃这个权值了。

    再回到这道题目,这道题获得权值的条件是这个点被控制或这个点相邻的 4 个点都被控制。 这个“或”并不太好处理,我们就把这个条件拆成两个不相交的条件:

    1)这个点被控制,可以获得权值。

    2)这个点没有被控制且相邻的4个点都被控制,可以获得权值。

    这样的话第一个条件就是不控制这个点需要付出的代价,第二个条件是“这个点没有被控制且相邻的4个点都被控制”,只要有一个点不符合就要割掉这个权值。

    但是这些需要同时满足的条件有“被控制”和“不被控制”,直接用“文理分科”的建图方式是方向不一致的。

    所以我们利用矩阵可以黑白染色成为二分图的性质,将矩阵的格子黑白染色之后,对于白点和黑点用相反的方式连边,这样黑点的“被控制”和白点的“不被控制”就是一个方向的了。

    注意刚开始时预先加到答案里的权值是给定权值的两倍,因为我们将权值分成了两种情况。

    代码

    #include <iostream>
    #include <cstdlib>
    #include <cstdio>
    #include <cstring>
    #include <cmath>
    #include <algorithm>
    
    using namespace std;
    
    inline int gmin(int a, int b) {return a < b ? a : b;}
    
    const int MaxMap = 50 + 5, MaxN = 5000 + 5, MaxM = 100000 + 5, INF = 999999999;
    const int Dx[5] = {0, 0, 1, -1}, Dy[5] = {1, -1, 0, 0};
    
    int n, m, nm, Tot, Ans, S, T;
    int f[MaxMap][MaxMap], A[MaxMap][MaxMap], B[MaxMap][MaxMap], d[MaxN], Num[MaxN];
    
    struct Edge
    {
    	int v, w;
    	Edge *Next, *Other;
    } E[MaxM], *P = E, *Point[MaxN], *Last[MaxN];
    
    inline void AddEdge(int x, int y, int z)
    {
    	Edge *Q = ++P; ++P;
    	P -> v = y; P -> w = z;
    	P -> Next = Point[x]; Point[x] = P; P -> Other = Q;
    	Q -> v = x; Q -> w = 0;
    	Q -> Next = Point[y]; Point[y] = Q; Q -> Other = P;
    }
    
    inline bool Inside(int x, int y)
    {
    	if (x < 1 || x > n) return false;
    	if (y < 1 || y > m) return false;
    	return true;
    }
     
    int DFS(int Now, int Flow)
    {
    	if (Now == T) return Flow;
    	int ret = 0;
    	for (Edge *j = Last[Now]; j; j = j -> Next)
    		if (j -> w && d[Now] == d[j -> v] + 1)
    		{
    			Last[Now] = j;
    			int p = DFS(j -> v, gmin(Flow - ret, j -> w));
    			ret += p; j -> w -= p; j -> Other -> w += p;
    			if (ret == Flow) return ret;
    		}
    	if (d[S] >= Tot) return ret;
    	if (--Num[d[Now]] == 0) d[S] = Tot;
    	++Num[++d[Now]];
    	Last[Now] = Point[Now];
    	return ret;
    }
    
    int main()
    {
    	scanf("%d%d", &n, &m);
    	nm = n * m;
    	for (int i = 1; i <= n; ++i)
    		for (int j = 1; j <= m; ++j)
    			f[i][j] = (i - 1) * m + j;
    	for (int i = 1; i <= n; ++i)
    		for (int j = 1; j <= m; ++j)
    			scanf("%d", &A[i][j]);
    	for (int i = 1; i <= n; ++i)
    		for (int j = 1; j <= m; ++j)
    		{
    			scanf("%d", &B[i][j]);
    			Ans += B[i][j] * 2;
    		}
    	Tot = 2 * nm; S = ++Tot; T = ++Tot;
    	int x, y;
    	for (int i = 1; i <= n; ++i)
    		for (int j = 1; j <= m; ++j)
    		{
    			if ((i + j) & 1) 
    			{
    				AddEdge(f[i][j], T, A[i][j]); 
    				AddEdge(S, f[i][j], B[i][j]);
    				AddEdge(nm + f[i][j], T, B[i][j]);
    				AddEdge(f[i][j], nm + f[i][j], INF);
    				for (int k = 0; k < 4; ++k)
    				{
    					x = i + Dx[k]; y = j + Dy[k];
    					if (!Inside(x, y)) continue;
    					AddEdge(f[x][y], nm + f[i][j], INF);
    				}
    			}
    			else 
    			{
    				AddEdge(S, f[i][j], A[i][j]);
    				AddEdge(f[i][j], T, B[i][j]);
    				AddEdge(S, nm + f[i][j], B[i][j]);
    				AddEdge(nm + f[i][j], f[i][j], INF);
    				for (int k = 0; k < 4; ++k)
    				{
    					x = i + Dx[k]; y = j + Dy[k];
    					if (!Inside(x, y)) continue;
    					AddEdge(nm + f[i][j], f[x][y], INF);
    				}	
    			}
    		}
    	memset(d, 0, sizeof(d));
    	memset(Num, 0, sizeof(Num)); Num[0] = Tot;
    	for (int i = 1; i <= Tot; ++i) Last[i] = Point[i];
    	while (d[S] < Tot) Ans -= DFS(S, INF);
    	printf("%d
    ", Ans);
    	return 0;
    }
    

      

  • 相关阅读:
    494. Target Sum 添加标点符号求和
    636. Exclusive Time of Functions 进程的执行时间
    714. Best Time to Buy and Sell Stock with Transaction Fee有交易费的买卖股票
    377. Combination Sum IV 返回符合目标和的组数
    325. Maximum Size Subarray Sum Equals k 和等于k的最长子数组
    275. H-Index II 递增排序后的论文引用量
    274. H-Index论文引用量
    RabbitMQ学习之HelloWorld(1)
    java之struts2的数据处理
    java之struts2的action的创建方式
  • 原文地址:https://www.cnblogs.com/JoeFan/p/4620622.html
Copyright © 2011-2022 走看看