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

    题面

    BZOJ传送门
    Luogu传送门

    分析

    这道题又出现了二元关系,于是我们只需要解方程确定怎么连边就行了
    在这里插入图片描述
    假设跟SS分在一块是选文科,跟TT分在一块是选理科,先加上所有的收益,再来考虑如何让需要减去的代价最小.我们来看看代价的方程

    定义AA表示选文科的收益,BB表示选理科的收益,有:

    • a+b=Ax+Ay+Ax,ylarge a+b=A_x+A_y+A_{x,y}
    • c+d=Bx+By+Bx,ylarge c+d=B_x+B_y+B_{x,y}
    • a+e+d=Ax+By+Ax,y+Bx,ylarge a+e+d=A_x+B_y+A_{x,y}+B_{x,y}
    • b+e+c=Bx+Ay+Ax,y+Bx,ylarge b+e+c=B_x+A_y+A_{x,y}+B_{x,y}

    能够解出来

    • a=Ax+Ax,y2large a=A_x+frac{A_{x,y}}2
    • b=Ay+Ax,y2large b=A_y+frac{A_{x,y}}2
    • c=Bx+Bx,y2large c=B_x+frac{B_{x,y}}2
    • d=By+Bx,y2large d=B_y+frac{B_{x,y}}2
    • e=Ax,y2+Bx,y2large e=frac{A_{x,y}}2+frac{B_{x,y}}2

    所以我们只需要把边权乘以二做最小割,然后用所有收益减去最小割的答案除以2就行了.

    CODE

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    typedef long long LL;
    char cb[1<<15],*cs=cb,*ct=cb;
    #define getc() (cs==ct && (ct = (cs = cb) + fread(cb , 1 , 1<<15 , stdin),cs==ct)?0:*cs++)
    template<typename T>inline void read(T &num) {
        char ch; while((ch=getchar())<'0'||ch>'9');
        for(num=0;ch>='0'&&ch<='9';num=num*10+ch-'0',ch=getchar());
    }
    
    const int inf = 1e9;
    const int MAXN = 10005;
    const int MAXM = 2000005;
    const int dx[] = { 1, -1, 0, 0, 0 };
    const int dy[] = { 0, 0, -1, 1, 0 };
    int n, m, fir[MAXN], S, T, cnt;
    struct edge { int to, nxt; int c; }e[MAXM];
    inline void add(int u, int v, int cc, int rc=0) {
    	e[cnt] = (edge){ v, fir[u], cc }; fir[u] = cnt++;
    	e[cnt] = (edge){ u, fir[v], rc }; fir[v] = cnt++;
    }
    int dis[MAXN], vis[MAXN], info[MAXN], cur, q[MAXN];
    inline bool bfs() {
    	int head = 0, tail = 0;
    	vis[S] = ++cur; q[tail++] = S;
    	while(head < tail) {
    		int u = q[head++];
    		for(int i = fir[u]; ~i; i = e[i].nxt)
    			if(e[i].c && vis[e[i].to] != cur)
    				vis[e[i].to] = cur, dis[e[i].to] = dis[u] + 1, q[tail++] = e[i].to;
    	}
    	if(vis[T] == cur) memcpy(info, fir, (T+1)<<2);
    	return vis[T] == cur;
    }
    int dfs(int u, int Max) {
    	if(u == T || !Max) return Max;
    	int flow=0, delta;
    	for(int &i = info[u]; ~i; i = e[i].nxt)
    		if(e[i].c && dis[e[i].to] == dis[u] + 1 && (delta=dfs(e[i].to, min(e[i].c, Max-flow)))) {
    			e[i].c -= delta, e[i^1].c += delta, flow += delta;
    			if(flow == Max) return flow;
    		}
    	return flow;
    }
    inline int dinic() {
    	int flow=0, x;
    	while(bfs()) {
    		while((x=dfs(S, inf))) flow+=x;
    	}
    	return flow;
    }
    int sum, tmps[MAXN], tmpt[MAXN], A[105][105], B[105][105];
    inline int enc(int i, int j) { return (i-1)*m + j; }
    int main () {
    	memset(fir, -1, sizeof fir);
    	read(n); read(m); S = 0; T = n*m+1;
    	for(int i = 1, x; i <= n; ++i)for(int j = 1; j <= m; ++j)read(x), sum += x, tmps[enc(i,j)] += 2*x;
    	for(int i = 1, x; i <= n; ++i)for(int j = 1; j <= m; ++j)read(x), sum += x, tmpt[enc(i,j)] += 2*x;
    	for(int i = 1; i < n; ++i)for(int j = 1; j <= m; ++j)read(A[i][j]), sum += A[i][j], tmps[enc(i,j)] += A[i][j], tmps[enc(i+1,j)] += A[i][j];
    	for(int i = 1; i < n; ++i)for(int j = 1; j <= m; ++j)read(B[i][j]), sum += B[i][j], tmpt[enc(i,j)] += B[i][j], tmpt[enc(i+1,j)] += B[i][j];
    	for(int i = 1; i < n; ++i)for(int j = 1; j <= m; ++j)add(enc(i, j), enc(i+1, j), A[i][j]+B[i][j], A[i][j]+B[i][j]);
    	for(int i = 1; i <= n; ++i)for(int j = 1; j < m; ++j)read(A[i][j]), sum += A[i][j], tmps[enc(i,j)] += A[i][j], tmps[enc(i,j+1)] += A[i][j];
    	for(int i = 1; i <= n; ++i)for(int j = 1; j < m; ++j)read(B[i][j]), sum += B[i][j], tmpt[enc(i,j)] += B[i][j], tmpt[enc(i,j+1)] += B[i][j];
    	for(int i = 1; i <= n; ++i)for(int j = 1; j < m; ++j)add(enc(i, j), enc(i, j+1), A[i][j]+B[i][j], A[i][j]+B[i][j]);
    	for(int i = 1; i <= n*m; ++i) {
    		if(tmps[i]) add(S, i, tmps[i]);
    		if(tmpt[i]) add(i, T, tmpt[i]);
    	}
    	printf("%d
    ", sum-dinic()/2);
    }
    
  • 相关阅读:
    java9的JShell小工具和编译器两种自动优化
    运算符
    数据类型
    常量&&变量
    强化学习复习笔记
    强化学习复习笔记
    DQN算法原理详解
    语言模型评价指标Perplexity
    C++ STL标准容器插入删除算法的复杂度
    集束搜索beam search和贪心搜索greedy search
  • 原文地址:https://www.cnblogs.com/Orz-IE/p/12039410.html
Copyright © 2011-2022 走看看