BZOJ3894 文理分科
传送门
神仙建模。(想不出想不出)好早之前听的一道题了,完全没有印象了QAQ
就是最小割模型肯定比较好看出来
然后呢对于处理一个人周围的都选的一样的话,那么就应该是新建一个全文/理点,这几个人连inf,然后收益连源汇就可以。
(网络流要多大胆建点!)
查了好久发现cnt没赋1【猛虎落泪】
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<queue>
#define ll long long
#define inf 20021225
#define N 110
#define mxn 40010
using namespace std;
int art[N][N],sci[N][N],sa[N][N],ss[N][N];
struct edge{int to,lt,f;}e[mxn*20];
int in[mxn],n,m,cnt=1,dis[mxn],s,t;
void add(int x,int y,int f)
{
e[++cnt].to=y;e[cnt].lt=in[x];e[cnt].f=f;in[x]=cnt;
e[++cnt].to=x;e[cnt].lt=in[y];e[cnt].f=0;in[y]=cnt;
}
queue<int> que;
bool bfs()
{
while(!que.empty()) que.pop();
memset(dis,0,sizeof(dis));
dis[s]=1;que.push(s);
while(!que.empty())
{
int x=que.front();que.pop();
for(int i=in[x];i;i=e[i].lt)
{
int y=e[i].to;
if(dis[y]||!e[i].f) continue;
dis[y]=dis[x]+1;
if(y==t) return true;
que.push(y);
}
}
return false;
}
int dfs(int x,int flow)
{
if(x==t||!flow) return flow;
int cur=flow;
for(int i=in[x];i;i=e[i].lt)
{
int y=e[i].to;
if(dis[y]==dis[x]+1&&e[i].f)
{
int tmp=dfs(y,min(cur,e[i].f));
e[i].f-=tmp;e[i^1].f+=tmp;cur-=tmp;
if(!cur) return flow;
}
}
dis[x]=-1;
return flow-cur;
}
int dinic()
{
int ans=0;
while(bfs()) ans+=dfs(s,inf);
return ans;
}
int id(int x,int y,int dep)
{
return dep*n*m+m*(x-1)+y;
}
int xx[4]={0,0,1,-1},yy[4]={1,-1,0,0};
int main()
{
int x,y,i;
scanf("%d%d",&n,&m);
s=n*m*3+1;t=s+1;
int ans=0;
// s art t sci
for(x=1;x<=n;x++)
for(y=1;y<=m;y++)
{
scanf("%d",&art[x][y]);
ans+=art[x][y];
add(s,id(x,y,0),art[x][y]);
}
for(x=1;x<=n;x++)
for(y=1;y<=m;y++)
{
scanf("%d",&sci[x][y]);
ans+=sci[x][y];
add(id(x,y,0),t,sci[x][y]);
}
for(x=1;x<=n;x++)
for(y=1;y<=m;y++)
{
scanf("%d",&sa[x][y]);
ans+=sa[x][y];
add(s,id(x,y,1),sa[x][y]);
add(id(x,y,1),id(x,y,0),inf);
for(i=0;i<4;i++)
{
int tx=x+xx[i],ty=y+yy[i];
if(tx<=0||ty<=0||tx>n||ty>m) continue;
add(id(x,y,1),id(tx,ty,0),inf);
}
}
for(x=1;x<=n;x++)
for(y=1;y<=m;y++)
{
scanf("%d",&ss[x][y]);
ans+=ss[x][y];
add(id(x,y,2),t,ss[x][y]);
add(id(x,y,0),id(x,y,2),inf);
for(i=0;i<4;i++)
{
int tx=x+xx[i],ty=y+yy[i];
if(tx<=0||ty<=0||tx>n||ty>m) continue;
add(id(tx,ty,0),id(x,y,2),inf);
}
}
ans-=dinic();
printf("%d\n",ans);
return 0;
}