[國家集訓隊]happiness
阿新 • • 發佈:2020-08-02
題目連結
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');}