• BZOJ 2127: happiness [最小割]


    2127: happiness

    Time Limit: 51 Sec  Memory Limit: 259 MB
    Submit: 1815  Solved: 878
    [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的非负整数

    本题和上一题很相似,可以用相同的做法
    但是本题可以优化
    相邻两个人具有经典的棋盘黑白染色的特征,虽然本题貌似与二分图无关,这是句废话
    能不能在一人一点的基础上直接处理出神秘加成
    放弃文同时也是放弃了 神秘加成_文/2
    两个人都放弃文就成功的放弃了整个 神秘加成_文
    理同理
    但是一人选文一人选理两个神秘加成都不能要啊,但这样每个神秘加成只放弃了1/2
    那就再加两条边,链接相邻两个人,容量为(神秘加成_文+神秘加成_理)/2,割的时候一文一理时必定割去这条两条边之一
     
    提示:
    那两条边可以直接加无向边
    注意:
    煞笔Candy?数组开成[10005][10005] bzoj不是T就是M
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    using namespace std;
    const int N=1e4+5,M=1e5+5,INF=1e9;
    inline int read(){
        char c=getchar();int x=0,f=1;
        while(c<'0'||c>'9'){if(c=='-')f=-1; c=getchar();}
        while(c>='0'&&c<='9'){x=x*10+c-'0'; c=getchar();}
        return x*f;
    }
    
    int n,m,num,s,t,a[105][105],b[105][105],c,f[105][105],g[105][105],sum;
    struct edge{
        int v,c,f,ne;
    }e[M<<1];
    int cnt,h[N];
    inline void ins(int u,int v,int c){
        cnt++;
        e[cnt].v=v;e[cnt].c=c;e[cnt].f=0;e[cnt].ne=h[u];h[u]=cnt;
        cnt++;
        e[cnt].v=u;e[cnt].c=0;e[cnt].f=0;e[cnt].ne=h[v];h[v]=cnt;
    }
    inline void ins2(int u,int v,int c){
        cnt++;
        e[cnt].v=v;e[cnt].c=c;e[cnt].f=0;e[cnt].ne=h[u];h[u]=cnt;
        cnt++;
        e[cnt].v=u;e[cnt].c=c;e[cnt].f=0;e[cnt].ne=h[v];h[v]=cnt;
    }
    int q[N],head,tail,vis[N],d[N];
    bool bfs(){
        memset(vis,0,sizeof(vis));
        memset(d,0,sizeof(d));
        head=tail=1;
        d[s]=0;vis[s]=1;
        q[tail++]=s;
        while(head!=tail){
            int u=q[head++];
            for(int i=h[u];i;i=e[i].ne){
                int v=e[i].v;
                if(!vis[v]&&e[i].c>e[i].f){
                    vis[v]=1;
                    d[v]=d[u]+1;
                    q[tail++]=v;
                    if(v==t) return true;
                }
            }
        }
        return false;
    }
    int cur[N];
    int dfs(int u,int a){
        if(u==t||a==0) return a;
        int flow=0,f;
        for(int &i=cur[u];i;i=e[i].ne){
            int v=e[i].v;
            if(d[v]==d[u]+1&&(f=dfs(v,min(a,e[i].c-e[i].f)))>0){
                flow+=f;
                e[i].f+=f;
                e[((i-1)^1)+1].f-=f;
                a-=f;
                if(a==0) break;
            }
        }
        return flow;
    }
    int dinic(){
        int flow=0;
        while(bfs()){
            for(int i=s;i<=t;i++) cur[i]=h[i];
            flow+=dfs(s,INF);
        }
        return flow;
    }
    inline int id(int i,int j){return (i-1)*m+j;}
    int main(){
        //freopen("in.txt","r",stdin);
        n=read();m=read();
        s=0;t=n*m+1;
        for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) a[i][j]=read()<<1,sum+=a[i][j]>>1;
        for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) b[i][j]=read()<<1,sum+=b[i][j]>>1;
        for(int i=1;i<=n-1;i++) for(int j=1;j<=m;j++){
            c=read();a[i][j]+=c;a[i+1][j]+=c;sum+=c;
            f[i][j]+=c;
            //ins2(id(i,j),id(i+1,j),c);
        }
        for(int i=1;i<=n-1;i++) for(int j=1;j<=m;j++){
            c=read();b[i][j]+=c;b[i+1][j]+=c;sum+=c;
            f[i][j]+=c;
            //ins2(id(i,j),id(i+1,j),c);
        }
        for(int i=1;i<=n;i++) for(int j=1;j<=m-1;j++){
            c=read();a[i][j]+=c;a[i][j+1]+=c;sum+=c;
            g[i][j]+=c;
            //ins2(id(i,j),id(i,j+1),c);
        }
        for(int i=1;i<=n;i++) for(int j=1;j<=m-1;j++){
            c=read();b[i][j]+=c;b[i][j+1]+=c;sum+=c;
            g[i][j]+=c;
            //ins2(id(i,j),id(i,j+1),c);
        }
        for(int i=1;i<=n;i++) for(int j=1;j<=m;j++){
            ins(s,id(i,j),a[i][j]);
            ins(id(i,j),t,b[i][j]);
            ins2(id(i,j),id(i+1,j),f[i][j]);
            ins2(id(i,j),id(i,j+1),g[i][j]);
        }
        int ans=dinic();
        printf("%d",sum-(ans>>1));
    }
     
     
     
  • 相关阅读:
    别再重复造轮子了,利用list创建任意数据类型的链表
    可配置内存池实现
    简单内存池实现
    基于本博客版本中的循环缓冲的测试(Linux环境)
    循环缓冲实现(ring buffer/circular buffer)
    recvfrom超时设置
    Linux系统如何做性能测试?
    深入理解虚拟内存机制
    Linux 内核的测试和调试
    python学习之路 实现简单的计算机功能。
  • 原文地址:https://www.cnblogs.com/candy99/p/6258684.html
Copyright © 2020-2023  润新知