zoukankan      html  css  js  c++  java
  • [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;
    }
  • 相关阅读:
    hlgoj 1766 Cubing
    Reverse Linked List
    String to Integer
    Bitwise AND of Numbers Range
    Best Time to Buy and Sell Stock III
    First Missing Positive
    Permutation Sequence
    Next Permutation
    Gray Code
    Number of Islands
  • 原文地址:https://www.cnblogs.com/FallDream/p/bzoj2127.html
Copyright © 2011-2022 走看看