bzoj2127

2127: happiness

Time Limit: 51 Sec  Memory Limit: 259 MB
Submit: 2492  Solved: 1205
[Submit][Status][Discuss]

Description

高一一班的座位表是个n*m的矩阵,经过一个学期的相处,每个同学和前后左右相邻的同学互相成为了好朋友。这学期要分文理科了,每个同学对于选择文科与理科有着自己的喜悦值,而一对好朋友如果能同时选文科或者理科,那么他们又将收获一些喜悦值。作为计算机竞赛教练的scp大老板,想知道如何分配可以使得全班的喜悦值总和最大。

Input

第一行两个正整数n,m。接下来是六个矩阵第一个矩阵为n行m列 此矩阵的第i行第j列的数字表示座位在第i行第j列的同学选择文科获得的喜悦值。第二个矩阵为n行m列 此矩阵的第i行第j列的数字表示座位在第i行第j列的同学选择理科获得的喜悦值。第三个矩阵为n-1行m列 此矩阵的第i行第j列的数字表示座位在第i行第j列的同学与第i+1行第j列的同学同时选择文科获得的额外喜悦值。第四个矩阵为n-1行m列 此矩阵的第i行第j列的数字表示座位在第i行第j列的同学与第i+1行第j列的同学同时选择理科获得的额外喜悦值。第五个矩阵为n行m-1列 此矩阵的第i行第j列的数字表示座位在第i行第j列的同学与第i行第j+1列的同学同时选择文科获得的额外喜悦值。第六个矩阵为n行m-1列 此矩阵的第i行第j列的数字表示座位在第i行第j列的同学与第i行第j+1列的同学同时选择理科获得的额外喜悦值。

Output

输出一个整数,表示喜悦值总和的最大值

Sample Input

1 2
1 1
100 110
1
1000

Sample Output

1210
【样例说明】
两人都选理,则获得100+110+1000的喜悦值。
【数据规模】
对于100%以内的数据,n,m<=100 所有喜悦值均为小于等于5000的非负整数

 

转载自http://blog.csdn.net/vmurder/article/details/42609669

 

#include <queue>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define N 50005
#define M 300000
#define P 105
#define inf 0x3f3f3f3f
using namespace std;
struct KSD
{
    int v,len,next;
}e[M];
int head[N],cnt;
inline void add(int u,int v,int len)
{
    e[++cnt].v=v;
    e[cnt].len=len;
    e[cnt].next=head[u];
    head[u]=cnt;
    e[++cnt].v=u;
    e[cnt].len=len;
    e[cnt].next=head[v];
    head[v]=cnt;
}
int s,t,d[N];
queue<int>q;
bool bfs()
{
    while(!q.empty())q.pop();
    memset(d,0,sizeof(d));
    int i,u,v;
    q.push(s),d[s]=1;
    while(!q.empty())
    {
        u=q.front(),q.pop();
        for(i=head[u];i;i=e[i].next)
        {
            v=e[i].v;
            if(!d[v]&&e[i].len)
            {
                d[v]=d[u]+1;
                if(v==t)return 1;
                q.push(v);
            }
        }
    }
    return 0;
}
int dinic(int x,int flow)
{
    if(x==t)return flow;
    int remain=flow,i,v,k;
    for(i=head[x];i&&remain;i=e[i].next)
    {
        v=e[i].v;
        if(d[v]==d[x]+1&&e[i].len)
        {
            k=dinic(v,min(remain,e[i].len));
            if(!k)d[v]=0;
            e[i].len-=k,e[i^1].len+=k;
            remain-=k;
        }
    }
    return flow-remain;
}
int n,m,id[P][P];
int sum,maxflow;
void build()
{
    int i,j,a,temp;
    scanf("%d%d",&n,&m),temp=n*m;
    s=n*m+2*(n-1)*m+2*n*(m-1)+1,t=n*m+2*(n-1)*m+2*n*(m-1)+2;
    for(i=1;i<=n;i++)for(j=1;j<=m;j++)id[i][j]=++cnt;
        cnt=1;
    // 第一个矩阵为n行m列 此矩阵的第i行第j列的数字表示座位在第i行第j列的同学选择文科获得的喜悦值。
    for(i=1;i<=n;i++)for(j=1;j<=m;j++)
    {
        scanf("%d",&a);
        sum+=a;
        add(s,id[i][j],a);
    }
    // 第二个矩阵为n行m列 此矩阵的第i行第j列的数字表示座位在第i行第j列的同学选择理科获得的喜悦值。
    for(i=1;i<=n;i++)for(j=1;j<=m;j++)
    {
        scanf("%d",&a);
        sum+=a;
        add(id[i][j],t,a);
    }
    // 第三个矩阵为n-1行m列 此矩阵的第i行第j列的数字表示座位在第i行第j列的同学与第i+1行第j列的同学同时选择文科获得的额外喜悦值。
    for(i=1;i<n;i++)for(j=1;j<=m;j++)
    {
        scanf("%d",&a);
        sum+=a,++temp;
        add(id[i][j],temp,a),add(id[i+1][j],temp,a);
        add(s,temp,a);
    }
    // 第四个矩阵为n-1行m列 此矩阵的第i行第j列的数字表示座位在第i行第j列的同学与第i+1行第j列的同学同时选择理科获得的额外喜悦值。
    for(i=1;i<n;i++)for(j=1;j<=m;j++)
    {
        scanf("%d",&a);
        sum+=a,++temp;
        add(id[i][j],temp,a),add(id[i+1][j],temp,a);
        add(temp,t,a);
    }
    // 第五个矩阵为n行m-1列 此矩阵的第i行第j列的数字表示座位在第i行第j列的同学与第i行第j+1列的同学同时选择文科获得的额外喜悦值。
    for(i=1;i<=n;i++)for(j=1;j<m;j++)
    {
        scanf("%d",&a);
        sum+=a,++temp;
        add(id[i][j],temp,a),add(id[i][j+1],temp,a);
        add(s,temp,a);
    }
    // 第六个矩阵为n行m-1列 此矩阵的第i行第j列的数字表示座位在第i行第j列的同学与第i行第j+1列的同学同时选择理科获得的额外喜悦值。
    for(i=1;i<=n;i++)for(j=1;j<m;j++)
    {
        scanf("%d",&a);
        sum+=a,++temp;
        add(id[i][j],temp,a),add(id[i][j+1],temp,a);
        add(temp,t,a);
    }
}
int main()
{
//    freopen("test.in","r",stdin);
    build();
    while(bfs())maxflow+=dinic(s,inf);
    printf("%d\n",sum-maxflow);
    return 0;
}
posted @ 2017-11-30 21:53  _wsy  阅读(173)  评论(0编辑  收藏  举报