您的位置:首页 > 其它

【NOI2015模拟9.9】文理分科

2017-04-19 20:24 381 查看

Description



Input



Output

一行表示最大的满意值

Sample Input

3 4

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

152

Solution

二元关系的裸题,就是限制略微有点不一样

没有学过二元关系的建议先看看某些大神关于二元关系的介绍

也可以看看我的另一篇博客,点这里进入(当然没有大神写的好)

这次的限制是周围的人全部要选同样的

那么可以对于每个点,多创建两个点,分别表示这个点的周围全部选了文科或全部选了理科,分别表示为x’和x”

构建最小割模型,连边方式如下:

点x归为S集表示选理科,T集表示选文科

点x’或x”归为S集表示不是真的,T集表示为真

源点向所有点连容量为理科的喜悦值

所有点向汇点连容量为文科的喜悦值

暂时只考虑x’即文科全选

源点向x’连0

x’向汇点连x的附加值

x向x’连x的附加值

为什么是对的呢?

假设x选了理科,即割了x->T的边

那么x’->T的边也一定会被割,否则就不是割了,x’便归为S,也就是不满足全选文科,不矛盾

假如x选了文科,即割了S->x的边

那么S->x’的边也会被割,但容量为0,同时x’归为了T,也就是满足全选文科,不矛盾

接着为了保证条件,所有与x’相邻的点y向x连正无穷,即如果y归为S即选理科,那么x’也一定归为S即不满足全选文科

理科反过来就行了

答案就是输入的所有数减最小割

Code

#include<cstdio>
#include<algorithm>
#include<cstring>
#define fo(i,a,b) for(int i=a;i<=b;i++)
#define N 10100000
#define INF 214748347
#define po(i,j) ((i-1)*m+j)
using namespace std;
int next
,last
,data
,to
,S,T,ans,d
,bz
,tot=1;
void putin(int x,int y,int z)
{
next[++tot]=last[x];last[x]=tot;to[tot]=y;data[tot]=z;
next[++tot]=last[y];last[y]=tot;to[tot]=x;data[tot]=0;
}
bool bfs()
{
int i=0,j=1;
memset(bz,0,sizeof(bz));
bz[d[1]=S]=1;
while(i<j)
{
int x=d[++i];
for(int k=last[x];k;k=next[k]) if(bz[to[k]]==0&&data[k]>0) bz[to[k]]=bz[x]+1,d[++j]=to[k];
}
return bz[T]>0;
}
int dfs(int x,int t)
{
if(x==T) return t;
int ans=0;
for(int i=last[x];i;i=next[i])
if(bz[to[i]]==bz[x]+1&&data[i])
{
int y=to[i],jy=0;
jy=dfs(y,min(t,data[i]));
if(jy) data[i]-=jy,data[i^1]+=jy,ans+=jy,t-=jy;
if(t==0) return ans;
}
if(ans==0) bz[x]=-1;
return ans;
}
int main()
{
int n,m;scanf("%d%d",&n,&m);S=n*m*3+1;T=n*m*3+2;
fo(i,1,n) fo(j,1,m)
{
int x;scanf("%d",&x);putin(po(i,j),T,x);ans+=x;
}
fo(i,1,n) fo(j,1,m)
{
int x;scanf("%d",&x);putin(S,po(i,j),x);ans+=x;
if(i!=1) putin(po(i,j),po(i-1,j)+n*m,INF),putin(po(i-1,j)+2*n*m,po(i,j),INF);
if(j!=1) putin(po(i,j),po(i,j-1)+n*m,INF),putin(po(i,j-1)+2*n*m,po(i,j),INF);
if(i!=n) putin(po(i,j),po(i+1,j)+n*m,INF),putin(po(i+1,j)+2*n*m,po(i,j),INF);
if(j!=m) putin(po(i,j),po(i,j+1)+n*m,INF),putin(po(i,j+1)+2*n*m,po(i,j),INF);
}
fo(i,1,n) fo(j,1,m)
{
int x;scanf("%d",&x);ans+=x;
putin(po(i,j),n*m+po(i,j),x);
putin(n*m+po(i,j),T,x);
putin(S,n*m+po(i,j),0);
}
fo(i,1,n) fo(j,1,m)
{
int x;scanf("%d",&x);ans+=x;
putin(2*n*m+po(i,j),po(i,j),x);
putin(2*n*m+po(i,j),T,0);
putin(S,2*n*m+po(i,j),x);
}
while(bfs()) ans-=dfs(S,INF);
printf("%d",ans);
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: