• [bzoj2127]happiness


    来自FallDream的博客,未经允许,请勿转载,谢谢。


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

    文理分科的模型题....

    对于每一个点,假如割到S表示选理科,割到T表示选文科,这两条边的边权显然,然后对于每一个特殊的条件,建立一个新点。如果表示都选文科获得的喜悦值,那么从S向他连边,边权是喜悦值,然后它向那两个点连边,边权设成INF。理科同理。

    最后最小割。

    然后去网上搜了搜发现了牛逼做法,对边权进行变换使得不用建出新点,效率变高。有兴趣可以自己看看。

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #define INF 2000000000
    #define S 0
    #define T 50000
    #define num(x,y) ((x-1)*m+y)
    using namespace std;
    inline int read()
    {
        int x=0,f=1;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-') f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){x=x*10+ch-'0'; ch=getchar();}
        return x*f;
    }
    
    int cnt=1,head[T+5],c[T+5],n,m,d[T+5],q[T+5],top=0,id;
    unsigned int ans=0;
    struct edge{int to,next,w;}e[T*10];
    
    inline void ins(int f,int t,int w)
    {
        e[++cnt]=(edge){t,head[f],w};head[f]=cnt;
        e[++cnt]=(edge){f,head[t],0};head[t]=cnt;
    }
    
    bool bfs()
    {
        memset(d,0,sizeof(d));int i,j;
        for(d[q[top=i=1]=S]=1;i<=top;i++)
            for(int j=c[q[i]]=head[q[i]];j;j=e[j].next)
                if(e[j].w&&!d[e[j].to])
                    d[q[++top]=e[j].to]=d[q[i]]+1;
        return d[T];
    }
    
    int dfs(int x,int f)
    {
        if(x==T)return f;
        int used=0;
        for(int&i=c[x];i;i=e[i].next)
            if(e[i].w&&d[e[i].to]==d[x]+1)
            {
                int w=dfs(e[i].to,min(e[i].w,f-used));
                used+=w;e[i].w-=w;e[i^1].w+=w;
                if(used==f)return f;
            }
        return d[x]=-1,used;
    }
    
    int main()
    {
        n=read();m=read();id=num(n,m);
        for(int i=1;i<=n;i++)
            for(int j=1;j<=m;j++)
            {
                int x=read();ans+=x;
                ins(S,num(i,j),x);
            }
        for(int i=1;i<=n;i++)
            for(int j=1;j<=m;j++)
            {
                int x=read();ans+=x;
                ins(num(i,j),T,x);
            }
        for(int i=1;i<n;i++)
            for(int j=1;j<=m;j++)
            {
                int x=read();ans+=x;
                ins(S,++id,x);
                ins(id,num(i,j),INF);
                ins(id,num(i+1,j),INF);
            }
        for(int i=1;i<n;i++)
            for(int j=1;j<=m;j++)
            {
                int x=read();ans+=x;
                ins(++id,T,x);
                ins(num(i,j),id,INF);
                ins(num(i+1,j),id,INF);
            }
        for(int i=1;i<=n;i++)
            for(int j=1;j<m;j++)
            {
                int x=read();ans+=x;
                ins(S,++id,x);
                ins(id,num(i,j),INF);
                ins(id,num(i,j+1),INF);
            }
        for(int i=1;i<=n;i++)
            for(int j=1;j<m;j++)
            {
                int x=read();ans+=x;
                ins(++id,T,x);
                ins(num(i,j),id,INF);
                ins(num(i,j+1),id,INF);
            }
        while(bfs()) ans-=dfs(S,INF);
        printf("%u
    ",ans);
        return 0;
    }
  • 相关阅读:
    在 Ubuntu上使用 MySQL
    Ubuntu/CentOs 搭建SVN服务器
    一个简单的零配置命令行HTTP服务器
    Windows 环境下 NodeJs 开发 Log
    AngularJS
    thinkphp5.0使用workerman多线程实例
    bat自动备份数据库文件
    mysql.ini配置优化速度参考
    php解析识别二维码内容
    windows屏蔽windows错误报告提示框
  • 原文地址:https://www.cnblogs.com/FallDream/p/bzoj2127.html
Copyright © 2020-2023  润新知