1. 程式人生 > 實用技巧 >[國家集訓隊]happiness

[國家集訓隊]happiness

題目連結

happiness

description

太長了,還是自己看題目連結吧.(逃)

solution:

最小割好題.對於每個人,我們可以將其拆點拆為兩部分:本身的貢獻和額外的貢獻,對於每部分連向超級源點的邊為選文的貢獻,連向超級匯點的邊為選理的貢獻,然後從第一部分文流向第二部分理,第二部分文流向第一部分理即可.然後用總值減去最小割即可.

(某個傻X作者由於匯點寫成源點調了一個下午bug交了二十次全WA正自閉中.)

code

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<queue>
#include<map>
#include<set>
#define R register
#define next kdjadskfj
#define debug puts("mlg")
#define mod 1000000009
#define Mod(x) ((x%mod+mod)%mod)
//#define pos(i,j) ((((i-1)*m)+j))
//#define pos1(i,j) ((pos(i,j)+11000))
//#define pos2(i,j) ((pos1(i,j)+22000))
using namespace std;
typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
inline ll read();
inline void write(ll x);
inline void writeln(ll x);
inline void writesp(ll x);
ll n,m,ans,sum;
ll head[2100000],c[2100000],tot=1,next[2100000],to[2100000];
ll S,T;
ll d[1400000]; 
queue<ll>q;

inline ll pos(ll i,ll j){return (i-1)*m+j;}

inline ll pos1(ll i,ll j){return pos(i,j)+n*m;}

inline ll pos2(ll i,ll j){return pos1(i,j)+n*m;}

inline void add(ll x,ll y,ll u){to[++tot]=y;next[tot]=head[x];head[x]=tot;c[tot]=u;}

inline void Link(ll x,ll y,ll u){add(x,y,u);add(y,x,0);}

bool bfs(){
	memset(d,0,sizeof d);
	while(!q.empty())q.pop();
	q.push(S);d[S]=1;
	while(!q.empty()){
		ll x=q.front();
		q.pop();
		for(R ll i=head[x],ver;i;i=next[i]){
			ver=to[i];
			if(!d[ver]&&c[i]){
				q.push(ver);
				d[ver]=d[x]+1;
				if(ver==T) return true;
			}
		}
	}
	return false;
}

ll dinic(ll x,ll flow){
	if(x==T||!flow) return flow;
	ll rest=flow,k;
	for(R ll i=head[x],ver;i&&rest;i=next[i]){
		ver=to[i];
		if(d[ver]==d[x]+1&&c[i]){
			k=dinic(ver,min(c[i],rest));
			if(!k) d[ver]=0;
			rest-=k;
			c[i]-=k;
			c[i^1]+=k;
		}
	}
	return flow-rest;
}


int main(){	
	n=read();m=read();
	S=n*m*3+1;T=n*m*3+2;
	for(R ll i=1,x;i<=n;i++){
		for(R ll j=1;j<=m;j++){
			x=read();
			ans+=x;
			Link(S,pos(i,j),x);
		}
	}
	for(R ll i=1,x;i<=n;i++){
		for(R ll j=1;j<=m;j++){
			x=read();
			ans+=x;
			Link(pos(i,j),T,x);
		}
	}
	for(R ll i=1,x;i<n;i++){
		for(R ll j=1;j<=m;j++){
			x=read();
			ans+=x;
			Link(S,pos1(i,j),x);
			Link(pos1(i,j),pos(i,j),x);
			Link(pos1(i,j),pos(i+1,j),x);
		}
	}
	for(R ll i=1,x;i<n;i++){
		for(R ll j=1;j<=m;j++){
			x=read();
			ans+=x;
			Link(pos2(i,j),T,x);
			Link(pos(i,j),pos2(i,j),x);
			Link(pos(i+1,j),pos2(i,j),x);
		}
	}
	for(R ll i=1,x;i<=n;i++){
		for(R ll j=1;j<m;j++){
			x=read();
			ans+=x;
			Link(S,pos1(i,j),x);
			Link(pos1(i,j),pos(i,j),x);
			Link(pos1(i,j),pos(i,j+1),x);
		}
	}
	for(R ll i=1,x;i<=n;i++){
		for(R ll j=1;j<m;j++){
			x=read();
			ans+=x;
			Link(pos2(i,j),T,x);
			Link(pos(i,j),pos2(i,j),x);
			Link(pos(i,j+1),pos2(i,j),x);
		}
	}
	ll _flow;
	while(bfs()){
		while(_flow=dinic(S,(((ull)1<<62)))) sum+=_flow;
	}
	write(ans-sum);
}
inline ll read(){ll x=0,t=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-') t=-1;ch=getchar();}while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}return x*t;}
inline void write(ll x){if(x<0){putchar('-');x=-x;}if(x<=9){putchar(x+'0');return;}write(x/10);putchar(x%10+'0');}
inline void writesp(ll x){write(x);putchar(' ');}
inline void writeln(ll x){write(x);putchar('\n');}