其实也就卡了卡常,,,
先考虑没有same_art和same_science 。
起点用art的流量连向每个点,该点再用science的流量连向终点,断开哪边相当于少了哪边收益。
先全部收益加起来,再减去最小割即可。
那有same这些情况怎么办呢。
考虑新建节点v,起点以same_art连向v,断开即代表不获得这段收益。如何避免这个点不断开s的同时它覆盖区的点断开了s?再用v点向覆盖区连权值为inf的边,即可保证覆盖区的点要断则该点必断。same_science同理,在下不加以赘述。
528ms,勉强能卡过,,
#include<bits/stdc++.h> #include<cstdio> #include<cmath> #include<cstring> #include<cstdlib> #include<algorithm> #include<queue> #include<deque> #include<list> #include<set> #include<vector> #include<iostream> #define ll int #define re register #define inf 0x7f7f7ff #define inl inline #define sqr(x) (x*x) //#define eps 1e-8 #define debug printf("debug "); //#pragma comment(linker, "/STACK:1024000000,1024000000") //#pragma GCC optimize (2) //#pragma G++ optimize (2) using namespace std; const ll mod=51123987; const ll MAXN=105; inl ll read() { re ll x = 0; re int f = 1; char ch = getchar(); while(ch<'0'||ch>'9') { if(ch== '-' ) f = -1; ch = getchar(); } while(ch>='0'&&ch<='9') {x=(x<<1)+(x<<3)+(ch^48);ch=getchar();} return x * f; } inl char readc() { char ch=getchar(); while(('z'<ch||ch<'a')&&('Z'<ch||ch<'A')) ch=getchar(); return ch; } inl void write(re ll x){ if(x>=10)write(x/10); putchar(x%10+'0'); } inl void writeln(re ll x){ if(x<0) {x=-x;putchar('-');} write(x); puts(""); } inl ll gcd(re ll x,re ll y){while(y^=x^=y^=x%=y);return x;} inl ll Lcm(re ll a,re ll b) {return a/gcd(a,b)*b;} inl void FR() { freopen(".in","r",stdin); freopen(".out","w",stdout); } inl void FC() { fclose(stdin); fclose(stdout); } struct edge{ ll u,v,w,nxt; }e[400005<<1]; ll ans,n,m,cnt=1,head[200005<<1],s,t,sst; ll dx[10]={0,0,0,1,-1}; ll dy[10]={0,1,-1,0,0}; inl void adde(ll u,ll v,ll w) { e[++cnt].u=u;e[cnt].v=v; e[cnt].w=w;e[cnt].nxt=head[u]; head[u]=cnt; } ll d[200005<<1],cur[200005<<1]; inl bool bfs() { queue<ll>Q; for(re ll i=s;i<=sst;i++) d[i]=0; Q.push(s);d[s]=1; while(!Q.empty()) { re ll x=Q.front();Q.pop(); for(re ll h=head[x];h;h=e[h].nxt) { re ll v=e[h].v; if(e[h].w&&!d[v]) { d[v]=d[x]+1; if(v==t) return true ; Q.push(v); } } } return d[t]; } ll dfs(ll x,ll limit) { if(x==t) return limit; ll used=0; for(re ll h=cur[x];h;h=e[h].nxt) { if(used==limit) break; if(d[e[h].v]==d[x]+1&&e[h].w) { ll t=dfs(e[h].v,min(limit-used,e[h].w)); used+=t;e[h].w-=t;e[h^1].w+=t; } } if(!used) d[x]=0; return used; } int main() { // FR(); n=read(),m=read();s=0;t=n*m+1;sst=t; for(re ll i=1;i<=n;i++) { for(re ll j=1;j<=m;j++) { re ll x=read(); adde(s,(i-1)*m+j,x); adde((i-1)*m+j,s,0); ans+=x; } } for(re ll i=1;i<=n;i++) { for(re ll j=1;j<=m;j++) { re ll x=read(); adde((i-1)*m+j,t,x); adde(t,(i-1)*m+j,0); ans+=x; } } for(re ll i=1;i<=n;i++) { for(re ll j=1;j<=m;j++) { re ll x=read(); ans+=x;sst++; adde(s,sst,x);adde(sst,s,0); for(re ll k=0;k<=4;k++) { re ll xx=i+dx[k],yy=j+dy[k]; if(xx&&xx<=n&&yy&&yy<=m) { adde(sst,(xx-1)*m+yy,inf); adde((xx-1)*m+yy,sst,0); } } } } for(re ll i=1;i<=n;i++) { for(re ll j=1;j<=m;j++) { re ll x=read(); ans+=x;sst++; adde(sst,t,x);adde(t,sst,0); for(re ll k=0;k<=4;k++) { re ll xx=i+dx[k],yy=j+dy[k]; if(xx&&xx<=n&&yy&&yy<=m) { adde((xx-1)*m+yy,sst,inf); adde(sst,(xx-1)*m+yy,0); } } } } while(bfs()) { memcpy(cur,head,sizeof(cur)); ans-=dfs(s,inf); } writeln(ans); // FC(); return 0; }