3894: 文理分科
Time Limit: 10 Sec Memory Limit: 512 MBSubmit: 521 Solved: 311
[ Submit][ Status][ Discuss]
Description
Input
Output
Sample Input
13 2 4 13
7 13 8 12
18 17 0 5
8 13 15 4
11 3 8 11
11 18 6 5
1 2 3 4
4 2 3 2
3 1 0 4
3 2 3 2
0 2 2 1
0 2 4 4
Sample Output
HINT
令S集为学文,T集为学理
每个人学文或者学理的满意度很好连边
如果某个集合内的人都学理会获得一个满意度,那么就新加一个点,将集合内的所有人向这个点连流量为正无穷的边,再从这个点向T连一条流量为满意度的边,表示集合内任意一个人学文都要把这个点与T的边割掉
都学文同理
建完图之后跑最小割即可
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int n,m,len,S,T,ans;
const int INF=1000000000;
int to[300000],flow[300000],next[300000],h[300000];
int dis[31000],q[31000];
int hg[3][5]={0,0,0,0,0,0,1,-1,0,0,0,0,0,1,-1};
inline int read()
{
char y; int x=0,f=1; y=getchar();
while (y<'0' || y>'9') {if (y=='-') f=-1; y=getchar();}
while (y>='0' && y<='9') {x=x*10+int(y)-48; y=getchar();}
return x*f;
}
void insert(int x,int y,int z)
{
++len; to[len]=y; flow[len]=z; next[len]=h[x]; h[x]=len;
}
bool bfs()
{
memset(dis,-1,sizeof(dis)); int tail=1,head=0; q[tail]=S; dis[S]=0;
while (head<tail)
{
++head;
int u=h[q[head]];
while (u!=0)
{
if (dis[to[u]]==-1 && flow[u])
{
dis[to[u]]=dis[q[head]]+1;
++tail; q[tail]=to[u];
}
u=next[u];
}
}
if (dis[T]!=-1) return true;else return false;
}
int dicnic(int now,int sum)
{
if (now==T) return sum;
int sug=0;
int u=h[now];
while (u!=0)
{
if (flow[u] && dis[to[u]]==dis[now]+1)
{
int s=dicnic(to[u],min(sum-sug,flow[u]));
if (s)
{
sug+=s; flow[u]-=s; flow[u^1]+=s;
if (sug==sum) return sum;
}
}
u=next[u];
}
if (sug==0) dis[now]=-1; return sug;
}
int main()
{
freopen("main.in","r",stdin);
freopen("me.out","w",stdout);
len=1; ans=0;
n=read(); m=read();
S=3*n*m+1; T=S+1;
for (int i=1;i<=n;++i)
for (int j=1;j<=m;++j)
{
int ug=(i-1)*m+j;
int x=read(); insert(S,ug,x); insert(ug,S,0); ans+=x;
}
for (int i=1;i<=n;++i)
for (int j=1;j<=m;++j)
{
int ug=(i-1)*m+j;
int x=read(); insert(ug,T,x); insert(T,ug,0); ans+=x;
}
int cnt=n*m;
for (int i=1;i<=n;++i)
for (int j=1;j<=m;++j)
{
++cnt;
int x=read(); ans+=x;
insert(S,cnt,x); insert(cnt,S,0);
int ug=(i-1)*m+j; insert(cnt,ug,INF); insert(ug,cnt,0);
for (int k=1;k<=4;++k)
{
int u1=i+hg[1][k]; int u2=j+hg[2][k];
if (u1>0 && u1<=n && u2>0 && u2<=m)
{
int ug=(u1-1)*m+u2; insert(cnt,ug,INF); insert(ug,cnt,0);
}
}
}
for (int i=1;i<=n;++i)
for (int j=1;j<=m;++j)
{
++cnt;
int x=read(); ans+=x;
int ug=(i-1)*m+j; insert(ug,cnt,INF); insert(cnt,ug,0);
for (int k=1;k<=4;++k)
{
int u1=i+hg[1][k]; int u2=j+hg[2][k];
if (u1>0 && u1<=n && u2>0 && u2<=m)
{
int ug=(u1-1)*m+u2; insert(ug,cnt,INF); insert(cnt,ug,0);
}
}
insert(cnt,T,x); insert(T,cnt,0);
}
while (bfs())
{
ans-=dicnic(S,INF);
}
printf("%d",ans);
}