zoukankan      html  css  js  c++  java
  • [BZOJ2127]happiness-[网络流-最小割]

    Description

    传送门

    Solution

    按照最小割的思路考虑。

    根据题意,当两个人都选文(理),需要砍掉两个人都选理(文)的加成;如果两个人选的不一样,就要都砍掉。

    这是一个网络流建模的套路:

    如图。为了防止出现分数,我们把每条边边权*2。

    最后用总的喜悦值去掉网络流大小即可。(记得除以2)

    Code

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<queue>
    using namespace std;
    const int inf=1e9;
    
    int h[10020],tot=0;
    struct pas{int x,y,nxt,w,op,cost;}g[300100];
    int dep[10020],S,T;
    queue<int>q;
    struct DINIC{
    bool bfs()
    {
        int x;
        memset(dep,0,sizeof(dep));dep[S]=1;
        while (!q.empty()) q.pop();
        q.push(S);
        while (!q.empty())
        {
            x=q.front();q.pop();
            for (int i=h[x];i;i=g[i].nxt)
            if (!dep[g[i].y]&&g[i].w)
            {
                dep[g[i].y]=dep[x]+1;
                q.push(g[i].y);
                if (g[i].y==T) return 1;
            }
        }
        return 0;
    }
    int dfs(int x,int flow)
    {
        if (x==T||(!flow))return flow;
        int temp=0,js;
        for (int i=h[x];i;i=g[i].nxt)
        if (dep[g[i].y]==dep[x]+1&&g[i].w)
        {
            js=dfs(g[i].y,min(flow,g[i].w));
            if (js)
            {
                g[i].w-=js;
                g[g[i].op].w+=js;
                temp+=js;
                flow-=js;
                if (!flow) return temp;
            }
        }
        if (!temp) dep[x]=0;
        return temp;
    }
        int dinic()
        {
            int ans=0;
            while (bfs()) 
            ans+=dfs(S,inf);
            return ans;
        } 
     }D;
      
    void add(int x,int y,int w)
    {
        g[++tot].x=x;g[tot].y=y;g[tot].w=w;g[tot].nxt=h[x];g[tot].op=tot+1;h[x]=tot;
        g[++tot].x=y;g[tot].y=x;g[tot].w=0;g[tot].nxt=h[y];g[tot].op=tot-1;h[y]=tot;
    }
    
    int n,m,sum;
    int art[110][110],sci[110][110];
    int row_art[110][110],row_sci[110][110];
    int col_art[110][110],col_sci[110][110];//col-column
    int id(int x,int y){return (x-1)*m+y;}
    int main()
    {
        scanf("%d%d",&n,&m);
        S=0;T=id(n,m)+1;
        for (int i=1;i<=n;i++) for (int j=1;j<=m;j++)
        {
            scanf("%d",&art[i][j]);    sum+=art[i][j];
            art[i][j]*=2;
        }
        for (int i=1;i<=n;i++) for (int j=1;j<=m;j++)
        {
            scanf("%d",&sci[i][j]);    sum+=sci[i][j];
            sci[i][j]*=2;    
        }
        for (int i=1;i<n;i++) for (int j=1;j<=m;j++)
        {
            scanf("%d",&row_art[i][j]);sum+=row_art[i][j];    
            art[i][j]+=row_art[i][j];
            art[i+1][j]+=row_art[i][j];
        }
        for (int i=1;i<n;i++) for (int j=1;j<=m;j++)
        {
            scanf("%d",&row_sci[i][j]);sum+=row_sci[i][j];
            sci[i][j]+=row_sci[i][j];
            sci[i+1][j]+=row_sci[i][j];
            add(id(i,j),id(i+1,j),row_art[i][j]+row_sci[i][j]);
            add(id(i+1,j),id(i,j),row_art[i][j]+row_sci[i][j]);
        }
        for (int i=1;i<=n;i++) for (int j=1;j<m;j++)
        {
            scanf("%d",&col_art[i][j]);sum+=col_art[i][j];    
            art[i][j]+=col_art[i][j];
            art[i][j+1]+=col_art[i][j];        
        }
        for (int i=1;i<=n;i++) for (int j=1;j<m;j++)
        {
            scanf("%d",&col_sci[i][j]);sum+=col_sci[i][j];    
            sci[i][j]+=col_sci[i][j];
            sci[i][j+1]+=col_sci[i][j];    
            add(id(i,j),id(i,j+1),col_art[i][j]+col_sci[i][j]);
            add(id(i,j+1),id(i,j),col_art[i][j]+col_sci[i][j]);
        }
        for (int i=1;i<=n;i++) for (int j=1;j<=m;j++)
        {
            add(S,id(i,j),art[i][j]);
            add(id(i,j),T,sci[i][j]);
        }
        printf("%d",(sum*2-D.dinic())/2);
    }
  • 相关阅读:
    SpringMVC视图解析器
    JavaEE PO VO BO DTO POJO DAO 整理总结
    Android Studio JNI开发入门教程
    javah的使用
    右键“在此处打开命令行窗口”的一个小秘密
    URL和URI的区别
    自学使用
    Ribbon使用
    Eureka集群搭建
    ssm常见面试题
  • 原文地址:https://www.cnblogs.com/coco-night/p/9564881.html
Copyright © 2011-2022 走看看