Description
文理分科是一件很纠结的事情!(虽然看到这个题目的人肯定都没有纠
结过)
小P所在的班级要进行文理分科。他的班级可以用一个n*m的矩阵进行
描述,每个格子代表一个同学的座位。每位同学必须从文科和理科中选择
一科。同学们在选择科目的时候会获得一个满意值。满意值按如下的方式
得到:
1.如果第i行第秒J的同学选择了文科,则他将获得art[i][j]的满意值,如
果选择理科,将得到science[i][j]的满意值。
2.如果第i行第J列的同学选择了文科,并且他相邻(两个格子相邻当且
仅当它们拥有一条相同的边)的同学全部选择了文科,则他会更开
心,所以会增加same_art[i][j]的满意值。
3.如果第i行第j列的同学选择了理科,并且他相邻的同学全部选择了理
科,则增加same_science[i]j[]的满意值。
小P想知道,大家应该如何选择,才能使所有人的满意值之和最大。请
告诉他这个最大值。
Input
第一行为两个正整数:n,m
接下来n术m个整数,表示art[i][j];
接下来n术m个整数.表示science[i][j];
接下来n术m个整数,表示same_art[i][j];
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
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
HINT
样例说明
1表示选择文科,0表示选择理科,方案如下:
1 0 0 1
0 1 0 0
1 0 0 0
N,M<=100,读入数据均<=500
终于看到这题了。
S往所有点连边,流量为选文的满意值。
所有点往T连边,流量为选理的满意值。
然后新建节点。表示所有选文或者所有选理的满意值
如下面所说即可。。
/*
对于每一个人多建立两个新点,分别表示以这个点为中心的五个点全部选择文科和理科。记这两个点为S1和S2。
S1->以这个点为中心的五个点 f:INF
一这个点为中心的五个点->S2 f:INF*/
by
http://blog.csdn.net/jiangyuze831/article/details/43968571
//我只是不知道该怎么表述
#include<cstdio>
#include<string>
#include<cstring>
using namespace std;
struct line
{
int s,t;
int f;
int next;
}a[4000001];
int head[100001];
int edge;
int p;
int q[400001],d[400001];
inline void add(int s,int t,int f)
{
a[edge].next=head[s];
head[s]=edge;
a[edge].s=s;
a[edge].t=t;
a[edge].f=f;
}
inline bool bfs()
{
int l=0,r=0;
memset(q,0,sizeof(q));
r++;
q[r]=0;
memset(d,-1,sizeof(d));
d[0]=0;
int i,k;
while(l<r)
{
l++;
int k=q[l];
for(i=head[k];i!=0;i=a[i].next)
{
if(a[i].f>0&&d[a[i].t]==-1)
{
d[a[i].t]=d[k]+1;
r++;
q[r]=a[i].t;
}
}
}
if(d[p]>=0)
return true;
return false;
}
inline int dfs(int k,int s)
{
if(k==p)
return s;
int t=s;
int i;
for(i=head[k];i!=0;i=a[i].next)
{
if(d[a[i].t]==d[k]+1&&a[i].f>0)
{
int xx=dfs(a[i].t,min(s,a[i].f));
a[i].f-=xx;
if(i%2==0)
a[i-1].f+=xx;
else
a[i+1].f+=xx;
s-=xx;
}
}
return t-s;
}
inline int maxflow()
{
int s=0;
while(bfs())
s+=dfs(0,2100000000);
return s;
}
int main()
{
int n,m;
scanf("%d%d",&n,&m);
int i,j;
int sum=0;
int x;
for(i=1;i<=n;i++)
{
for(j=1;j<=m;j++)
{
scanf("%d",&x);
sum+=x;
edge++;
add(0,(i-1)*m+j,x);
edge++;
add((i-1)*m+j,0,0);
}
}
p=n*m*4;
for(i=1;i<=n;i++)
{
for(j=1;j<=m;j++)
{
scanf("%d",&x);
sum+=x;
edge++;
add((i-1)*m+j,p,x);
edge++;
add(p,(i-1)*m+j,0);
}
}
int d=n*m;
for(i=1;i<=n;i++)
{
for(j=1;j<=m;j++)
{
scanf("%d",&x);
sum+=x;
d++;
edge++;
add(0,d,x);
edge++;
add(d,0,0);
edge++;
add(d,(i-1)*m+j,2100000000);
edge++;
add((i-1)*m+j,d,0);
if(j>1)
{
edge++;
add(d,(i-1)*m+j-1,2100000000);
edge++;
add((i-1)*m+j-1,d,0);
}
if(j<m)
{
edge++;
add(d,(i-1)*m+j+1,2100000000);
edge++;
add((i-1)*m+j+1,d,0);
}
if(i<n)
{
edge++;
add(d,i*m+j,2100000000);
edge++;
add(i*m+j,d,0);
}
if(i>1)
{
edge++;
add(d,(i-2)*m+j,2100000000);
edge++;
add((i-2)*m+j,d,0);
}
}
}
for(i=1;i<=n;i++)
{
for(j=1;j<=m;j++)
{
scanf("%d",&x);
sum+=x;
d++;
edge++;
add(d,p,x);
edge++;
add(p,d,0);
edge++;
add((i-1)*m+j,d,2100000000);
edge++;
add(d,(i-1)*m+j,0);
if(j>1)
{
edge++;
add((i-1)*m+j-1,d,2100000000);
edge++;
add(d,(i-1)*m+j-1,0);
}
if(j<m)
{
edge++;
add((i-1)*m+j+1,d,2100000000);
edge++;
add(d,(i-1)*m+j+1,0);
}
if(i<n)
{
edge++;
add(i*m+j,d,2100000000);
edge++;
add(d,i*m+j,0);
}
if(i>1)
{
edge++;
add((i-2)*m+j,d,2100000000);
edge++;
add(d,(i-2)*m+j,0);
}
}
}
printf("%d\n",sum-maxflow());
return 0;
}