[题解] bzoj3894文理分科
题目链接
题目描述
\(n\)行\(m\)列的矩阵,每个人可以选文科或者理科。第\(i,j\)个人选文科贡献为\(a_{i,j}\),选理科贡献为\(b_{i,j}\),周围及自己选文科贡献为\(c_{i,j}\),周围及自己选理科贡献为\(d_{i,j}\)。
思路
建图方法见代码。
利用最大权闭合子图,考虑全选文科,初始值为\(\sum a_{i,j} c_{i,j}\)。
那么理科的贡献就为\(b_{i,j}\),全选理科的贡献为\(d_{i,j}\)。
不选文科的贡献为\(-a_{i,j}\),\(5\)人之中有一个不选的贡献为\(-c_{i,j}\)。
则内部构图中,有三个约束条件:
选了理科,则必不选文科。
选了\(d_{i,j}\),则四周及自己都必须选理科。
选了一个不选文科,则与这个点相关的\(c_{i,j}\)都必须破坏,及必选相关的\(-c_{i,j}\)。
则答案为\(\ sum a _ { I,j} b_{i,j} c_{i,j} d_{i,j})-mincut\)。
Code
#包含cstdio
#定义INF0x3f3f
const int MAXN=2e5 5
const int MaxM=1e 6 5;
结构边缘{ int To,Cap,Next}边[MAXM 1];
int head[MAXN],tot=1;
void Addedge(int u,int v,int w){ 0
边缘[ tot].下一个=头[u],边[tot]。To=v,edge[tot].Cap=w,head[u]=tot;
边缘[ tot].下一个=头部[v],边缘[tot].To=u,edge[tot].Cap=0,head[v]=tot;
}
int cur[MAXN],dep[MAXN],que[MAXN],qhead,qtail
int n,m,s,t;
int addx[]={0,0,1,-1,0 };
int addy[]={1,-1,0,0,0 };
int ans
int Min(int x,int y){ return x y x :y;}
布尔bfs(布尔限制){ 0
for(int I=s;I=t;i ) dep[i]=0,cur[I]=head[I];
qhead=1;qtail=1;que[1]=t;dep[t]=1;
while(qhead=qtail){ 0
int u=que[qhead];
for(int I=head[u];我;i=edge[i].下一个){ 0
int v=edge[i].到;
if(!副[v]边[i ^ 1].Cap(!限制||!(一(1)))(
dep[v]=dep[u]1;
que[qtail]=v;
if (v==s)返回1;
}
}
}
返回0;
}
int dfs(int u,int flow){ 0
if(u==t ||!流量)回流;
int rest=flow
for(int I=cur[u];我休息;i=edge[i].下一个){ 0
cur[u]=I;
int v=edge[i].到;
if(dep[v]==dep[u] - 1边[i].Cap) {
int del=dfs(v,Min(静止,边缘[i]).cap));
rest-=del;边缘cap-=del;边缘[我^ 1]。Cap=del
if(!del)dep[v]=-2;
}
}
回流休息;
}
int Dinic(){ 0
int res=0,流;
while (bfs(1)) while ((flow=dfs(s,INF)))RES=flow;
while (bfs(0)) while ((flow=dfs(s,INF)))RES=flow;
返回表示留数
}
int Get(int x,int y,int h){ 0
return(x-1)* m y n * m * h;
}
int main(){ 0
scanf('%d %d ',n,m);
s=0,t=4 * n * m ^ 1;
for(int I=1;I=n;I){ 0
for (int j=1,a;j=m;j ) {
scanf("% d ",a);
Addedge(Get(i,j,0),t,a);
ans=a;
}
}
for(int I=1;I=n;I){ 0
for (int j=1,a;j=m;j ) {
scanf("% d ",a);
Addedge(s,Get(i,j,1),a);
Addedge(Get(i,j,1),Get(i,j,0),INF);
ans=a;
}
}
for(int I=1;I=n;I){ 0
for (int j=1,a;j=m;j ) {
scanf("% d ",a);
Addedge(Get(i,j,2),t,a);
ans=a;
for(int k=0;K5;k){ 0
int ni=I addx[k];
int NJ=j addy[k];
if (ni 1 || ni n || nj 1 || nj m)继续;
Addedge(Get(ni,nj,0),Get(i,j,2),INF);
}
}
}
for(int I=1;I=n;I){ 0
for (int j=1,a;j=m;j ) {
scanf("% d ",a);
ans=a;
Addedge(s,Get(i,j,3),a);
for(int k=0;K5;k){ 0
int ni=I addx[k];
int NJ=j addy[k];
if (ni 1 || ni n || nj 1 || nj m)继续;
Addedge(Get(i,j,3),Get(ni,nj,1),INF);
}
}
}
printf('%d ',ans-Dinic());
返回0;
}
内容来源网络,如有侵权,联系删除,本文地址:https://www.230890.com/zhan/141448.html