• [国家集训队2011]happiness


    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的非负整数

    Solution

    唔,题解。

    那么这个题非常明显,就是文理分科模型的始祖。经过一番YY后我们可以确定要先默认拿到所有喜悦值,然后减去拿不到的。

    那么怎么搞呢,两种方法。这里说一下比较快的那一种。我们已经确定割边就相当于放弃部分收益。那么显而易见的是我们可以通过与源点连接权值为文科的边和与汇点连权值为理科的边表示是否选文选理。然后通过关系,可以比较容易的得出互相之间需要连边。那么连接。。算了看代码了,这种裸题不想解释。

    #pragma comment(linker, "/STACK:1024000000,1024000000")
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    #include<queue>
    #define re register
    #define inf 400000000
    #define MAXN 10005
    #define MAXM 200001
    using namespace std;
    int n,s,q,dis[2000011],t,l,cur[200051],m,tot,cnt;
    int id[101][101],a[101][101],b[101][101],a1[101][101],b1[101][101],a2[101][101],b2[101][101];
    struct po
    {
        int nxt,to,w;
    }edge[MAXM];
    int head[MAXN],dep[MAXN],num=-1;
    inline int read()
    {
        int x=0,c=1;
        char ch=' ';
        while((ch>'9'||ch<'0')&&ch!='-')ch=getchar();
        while(ch=='-')c*=-1,ch=getchar();
        while(ch<='9'&&ch>='0')x=x*10+ch-'0',ch=getchar();
        return x*c;
    }
    inline void add_edge(int from,int to,int w)
    {
        edge[++num].nxt=head[from];
        edge[num].to=to;
        edge[num].w=w;
        head[from]=num;
    }
    inline void add(int from,int to,int w)
    {
        add_edge(from,to,w);
        add_edge(to,from,0);
    }
    inline bool bfs()
    {
        memset(dep,0,sizeof(dep));
        queue<int> q;
        while(!q.empty())
        q.pop();
        q.push(s);
        dep[s]=1;
        while(!q.empty())
        {
            int u=q.front();
            q.pop();
            for(re int i=head[u];i!=-1;i=edge[i].nxt)
            {
                int v=edge[i].to;
                if(dep[v]==0&&edge[i].w>0)
                {
                    dep[v]=dep[u]+1;
                    if(v==t)
                    return 1;
                    q.push(v);
                }
            }
        }
        return 0;
    }
    inline int dfs(int u,int dis)
    {
        if(u==t)
        return dis;
        int diss=0;
        for(re int& i=cur[u];i!=-1;i=edge[i].nxt)
        {
            int v=edge[i].to;
            if(edge[i].w!=0&&dep[v]==dep[u]+1)
            {
                int check=dfs(v,min(dis,edge[i].w));
                if(check>0)
                {
                    dis-=check;
                    diss+=check;
                    edge[i].w-=check;
                    edge[i^1].w+=check;
                    if(dis==0) break;
                }
            }
        }
        return diss;
    }
    inline int dinic()
    {
        int ans=0;
        while(bfs())
        {
            for(re int i=0;i<=t;i++)
            cur[i]=head[i];
            while(int d=dfs(s,inf))
            ans+=d;
        }
        return ans;
    }
    inline int pd1(int x,int y)
    {
        int ans=0;
        if(x!=1) ans+=a1[x-1][y];
        if(x!=n) ans+=a1[x][y];
        if(y!=1) ans+=a2[x][y-1];
        if(y!=m) ans+=a2[x][y];
        return ans;
    }
    inline int pd2(int x,int y)
    {
        int ans=0;
        if(x!=1) ans+=b1[x-1][y];
        if(x!=n) ans+=b1[x][y];
        if(y!=1) ans+=b2[x][y-1];
        if(y!=m) ans+=b2[x][y];
        return ans;
    }
    int main() 
    {
        memset(head,-1,sizeof(head));
     	n=read();m=read();
     	s=0;t=n*m+1;
     	for(re int i=1;i<=n;i++)
     		for(re int j=1;j<=m;j++)
     			a[i][j]=read(),id[i][j]=++cnt,tot+=2*a[i][j];
     	for(re int i=1;i<=n;i++)
     		for(re int j=1;j<=m;j++)
     			b[i][j]=read(),tot+=2*b[i][j];
     	for(re int i=1;i<n;i++)
     		for(re int j=1;j<=m;j++)
     			a1[i][j]=read(),tot+=a1[i][j]+a1[i][j];
     	for(re int i=1;i<n;i++)
     		for(re int j=1;j<=m;j++)
     			b1[i][j]=read(),tot+=b1[i][j]+b1[i][j];
     	for(re int i=1;i<=n;i++)
     		for(re int j=1;j<m;j++)
     			a2[i][j]=read(),tot+=a2[i][j]+a2[i][j];
     	for(re int i=1;i<=n;i++)
     		for(re int j=1;j<m;j++)
     			b2[i][j]=read(),tot+=b2[i][j]+b2[i][j];
     	for(re int i=1;i<=n;i++)
     		for(re int j=1;j<=m;j++){
     			add(s,id[i][j],2*a[i][j]+pd1(i,j));
     			add(id[i][j],t,2*b[i][j]+pd2(i,j));
     			if(i!=1) add(id[i][j],id[i-1][j],a1[i-1][j]+b1[i-1][j]);
     			if(j!=1) add(id[i][j],id[i][j-1],a2[i][j-1]+b2[i][j-1]);
     			if(i!=n) add(id[i][j],id[i+1][j],a1[i][j]+b1[i][j]);
     			if(j!=m) add(id[i][j],id[i][j+1],a2[i][j]+b2[i][j]); 
     		}
     	cout<<(tot-dinic())/2;
        return 0;
    }
    
  • 相关阅读:
    让自己的网站或博客被百度收录的小技巧
    Linux cp一个文件夹时提示cp: omitting directory `test/'
    svn checkout 提示“由于连接方在一段时间后没有正确答复或连接的主机没有反应,连接尝试失败。”解决方法
    Linux iptables开放特定端口
    CentOS7使用iptables防火墙开放端口
    Linux平台的SVN服务器的配置及搭建
    官网svn提交到代码库,但是不能同步到web目录
    【LINUX】SVN 代码提交之后。同步到web目录下
    React Native For Android 架构初探
    腾讯QQ会员技术团队:以手机QQ会员H5加速为例,为你揭开sonic技术内幕
  • 原文地址:https://www.cnblogs.com/victorique/p/9084502.html
Copyright © 2020-2023  润新知