zoukankan      html  css  js  c++  java
  • [国家集训队]happiness 最小割 BZOJ 2127

    题目描述

    高一一班的座位表是个n*m的矩阵,经过一个学期的相处,每个同学和前后左右相邻的同学互相成为了好朋友。这学期要分文理科了,每个同学对于选择文科与理科有着自己的喜悦值,而一对好朋友如果能同时选文科或者理科,那么他们又将收获一些喜悦值。

    作为计算机竞赛教练的scp大老板,想知道如何分配可以使得全班的喜悦值总和最大。

    输入输出格式

    输入格式:

    第一行两个正整数n,m。

    接下来是六个矩阵

    • 第一个矩阵为n行m列

    此矩阵的第i行第j列的数字表示座位在第i行第j列的同学选择文科获得的喜悦值。

    • 第二个矩阵为n行m列

    此矩阵的第i行第j列的数字表示座位在第i行第j列的同学选择理科获得的喜悦值。

    • 第三个矩阵为n-1行m列

    此矩阵的第i行第j列的数字表示座位在第i行第j列的同学与第i+1行第j列的同学同时选择文科获得的额外喜悦值。

    • 第四个矩阵为n-1行m列

    此矩阵的第i行第j列的数字表示座位在第i行第j列的同学与第i+1行第j列的同学同时选择理科获得的额外喜悦值。

    • 第五个矩阵为n行m-1列

    此矩阵的第i行第j列的数字表示座位在第i行第j列的同学与第i行第j+1列的同学同时选择文科获得的额外喜悦值。

    • 第六个矩阵为n行m-1列

    此矩阵的第i行第j列的数字表示座位在第i行第j列的同学与第i行第j+1列的同学同时选择理科获得的额外喜悦值。

    输出格式:

    输出一个整数,表示喜悦值总和的最大值

    输入输出样例

    输入样例#1: 复制
    1 2
    1 1
    100 110
    1
    1000
    输出样例#1: 复制
    1210
    

    说明

    【样例说明】

    两人都选理,则获得100+110+1000的喜悦值。

    对于100%以内的数据,n,m<=100 所有喜悦值均为小于等于5000的非负整数

    考虑最小割:

    用 st 表示源点---文科,ed 表示 汇点 --- 理科;

    其中 A,B 为有关联的两个点;

    考虑建边:

    st--->A : A文+AB文/2,st--->B:B文+AB文/2;

    A--->ed: A理+AB理/2,B--->ed:B理+AB理/2;

    A<--->B:AB理/2+AB文/2;

    枚举最小割我们可以发现所有可能的情况都满足了;

    要使得高兴值最大,那么最小割最小;

    跑一边 dinic即可;

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cstdlib>
    #include<cstring>
    #include<string>
    #include<cmath>
    #include<map>
    #include<set>
    #include<vector>
    #include<queue>
    #include<bitset>
    #include<ctime>
    #include<deque>
    #include<stack>
    #include<functional>
    #include<sstream>
    //#include<cctype>
    //#pragma GCC optimize("O3")
    using namespace std;
    #define maxn 200005
    #define inf 0x3f3f3f3f
    #define INF 9999999999
    #define rdint(x) scanf("%d",&x)
    #define rdllt(x) scanf("%lld",&x)
    #define rdult(x) scanf("%lu",&x)
    #define rdlf(x) scanf("%lf",&x)
    #define rdstr(x) scanf("%s",x)
    typedef long long  ll;
    typedef unsigned long long ull;
    typedef unsigned int U;
    #define ms(x) memset((x),0,sizeof(x))
    const long long int mod = 1e9 + 7;
    #define Mod 1000000000
    #define sq(x) (x)*(x)
    #define eps 1e-3
    typedef pair<int, int> pii;
    #define pi acos(-1.0)
    const int N = 1005;
    #define REP(i,n) for(int i=0;i<(n);i++)
    typedef pair<int, int> pii;
    inline ll rd() {
    	ll x = 0;
    	char c = getchar();
    	bool f = false;
    	while (!isdigit(c)) {
    		if (c == '-') f = true;
    		c = getchar();
    	}
    	while (isdigit(c)) {
    		x = (x << 1) + (x << 3) + (c ^ 48);
    		c = getchar();
    	}
    	return f ? -x : x;
    }
    
    ll gcd(ll a, ll b) {
    	return b == 0 ? a : gcd(b, a%b);
    }
    ll sqr(ll x) { return x * x; }
    
    /*ll ans;
    ll exgcd(ll a, ll b, ll &x, ll &y) {
    	if (!b) {
    		x = 1; y = 0; return a;
    	}
    	ans = exgcd(b, a%b, x, y);
    	ll t = x; x = y; y = t - a / b * y;
    	return ans;
    }
    */
    
    
    
    ll qpow(ll a, ll b, ll c) {
    	ll ans = 1;
    	a = a % c;
    	while (b) {
    		if (b % 2)ans = ans * a%c;
    		b /= 2; a = a * a%c;
    	}
    	return ans;
    }
    
    
    int n, m;
    int st, ed;
    
    struct node {
    	int u, v, w, nxt;
    }edge[maxn<<1];
    
    int head[maxn], cnt;
    
    void addedge(int u, int v, int w) {
    	edge[cnt].u = u; edge[cnt].v = v; edge[cnt].w = w;
    	edge[cnt].nxt = head[u]; head[u] = cnt++;
    }
    
    int rk[maxn];
    
    int bfs() {
    	queue<int>q;
    	ms(rk);
    	rk[st] = 1; q.push(st);
    	while (!q.empty()) {
    		int tmp = q.front(); q.pop();
    		for (int i = head[tmp]; i != -1; i = edge[i].nxt) {
    			int to = edge[i].v;
    			if (rk[to] || edge[i].w <= 0)continue;
    			rk[to] = rk[tmp] + 1; q.push(to);
    		}
    	}
    	return rk[ed];
    }
    
    int dfs(int u, int flow) {
    	if (u == ed)return flow;
    	int add = 0;
    	for (int i = head[u]; i != -1 && add < flow; i = edge[i].nxt) {
    		int v = edge[i].v;
    		if (rk[v] != rk[u] + 1 || !(edge[i].w))continue;
    		int tmpadd = dfs(v, min(edge[i].w, flow - add));
    		if (!tmpadd) { rk[v] = -1; continue; }
    		edge[i].w -= tmpadd; edge[i ^ 1].w += tmpadd; add += tmpadd;
    	}
    	return add;
    }
    
    int ans;
    void dinic() {
    	while (bfs())ans += dfs(st, inf);
    }
    
    int a[200][200], b[200][200], id[200][200];
    int sum = 0;
    void build() {
    	int x; st = 0; ed = n * m + 1;
    	for (int i = 1; i < n; i++) {
    		for (int j = 1; j <= m; j++) {
    			rdint(x); sum += x;
    			a[i][j] += x; a[i + 1][j] += x;
    			addedge(id[i][j], id[i + 1][j], x);
    			addedge(id[i + 1][j], id[i][j], x);
    		}
    	}
    	for (int i = 1; i < n; i++) {
    		for (int j = 1; j <= m; j++) {
    			rdint(x); sum += x;
    			b[i][j] += x; b[i + 1][j] += x;
    			addedge(id[i][j], id[i + 1][j], x);
    			addedge(id[i + 1][j], id[i][j], x);
    		}
    	}
    	for (int i = 1; i <= n; i++) {
    		for (int j = 1; j < m; j++) {
    			rdint(x); sum += x;
    			a[i][j] += x; a[i][j + 1] += x;
    			addedge(id[i][j], id[i][j + 1], x);
    			addedge(id[i][j + 1], id[i][j], x);
    		}
    	}
    	for (int i = 1; i <= n; i++) {
    		for (int j = 1; j < m; j++) {
    			rdint(x); sum += x;
    			b[i][j] += x; b[i][j + 1] += x;
    			addedge(id[i][j], id[i][j + 1], x);
    			addedge(id[i][j + 1], id[i][j], x);
    		}
    	}
    	for (int i = 1; i <= n; i++) {
    		for (int j = 1; j <= m; j++) {
    			addedge(st, id[i][j], a[i][j]); addedge(id[i][j], st, 0);
    			addedge(id[i][j], ed, b[i][j]); addedge(ed, id[i][j], 0);
    		}
    	}
    }
    
    int main()
    {
    	//ios::sync_with_stdio(0);
    	rdint(n); rdint(m); memset(head, -1, sizeof(head)); //cnt = 1;
    	for (int i = 1; i <= n; i++) {
    		for (int j = 1; j <= m; j++) {
    			rdint(a[i][j]); sum += a[i][j]; a[i][j] <<= 1;
    		}
    	}
    	for (int i = 1; i <= n; i++) {
    		for (int j = 1; j <= m; j++) {
    			rdint(b[i][j]); sum += b[i][j]; b[i][j] <<= 1;
    		}
    	}
    	for (int i = 1; i <= n; i++)
    		for (int j = 1; j <= m; j++)id[i][j] = (i - 1)*m + j;
    	build(); dinic();
    	cout << sum - (ans >> 1) << endl;
        return 0;
    }
    
    EPFL - Fighting
  • 相关阅读:
    Hihocoder 1275 扫地机器人 计算几何
    CodeForces 771C Bear and Tree Jumps 树形DP
    CodeForces 778D Parquet Re-laying 构造
    CodeForces 785E Anton and Permutation 分块
    CodeForces 785D Anton and School
    CodeForces 785C Anton and Fairy Tale 二分
    Hexo Next 接入 google AdSense 广告
    如何统计 Hexo 网站的访问地区和IP
    Design and Implementation of Global Path Planning System for Unmanned Surface Vehicle among Multiple Task Points
    通过ODBC接口访问人大金仓数据库
  • 原文地址:https://www.cnblogs.com/zxyqzy/p/9993541.html
Copyright © 2011-2022 走看看