• BZOJ 3894: 文理分科 最小割


    3894: 文理分科

    题目连接:

    http://www.lydsy.com/JudgeOnline/problem.php?id=3894

    Description

    文理分科是一件很纠结的事情!(虽然看到这个题目的人肯定都没有纠
    结过)
    小P所在的班级要进行文理分科。他的班级可以用一个n*m的矩阵进行
    描述,每个格子代表一个同学的座位。每位同学必须从文科和理科中选择
    一科。同学们在选择科目的时候会获得一个满意值。满意值按如下的方式
    得到:
    1.如果第i行第秒J的同学选择了文科,则他将获得art[i][j]的满意值,如
    果选择理科,将得到science[i][j]的满意值。
    2.如果第i行第J列的同学选择了文科,并且他相邻(两个格子相邻当且
    仅当它们拥有一条相同的边)的同学全部选择了文科,则他会更开
    心,所以会增加same_art[i][j]的满意值。
    3.如果第i行第j列的同学选择了理科,并且他相邻的同学全部选择了理
    科,则增加same_science[i]j[]的满意值。
    小P想知道,大家应该如何选择,才能使所有人的满意值之和最大。请
    告诉他这个最大值。

    Input

    第一行为两个正整数:n,m
    接下来n术m个整数,表示art[i][j];
    接下来n术m个整数.表示science[i][j];
    接下来n术m个整数,表示same_art[i][j];

    Output

    输出为一个整数,表示最大的满意值之和

    Sample Input

    3 4

    13 2 4 13

    7 13 8 12

    18 17 0 5

    8 13 15 4

    11 3 8 11

    11 18 6 5

    1 2 3 4

    4 2 3 2

    3 1 0 4

    3 2 3 2

    0 2 2 1

    0 2 4 4

    Sample Output

    152

    Hint

    题意

    题解

    最小割

    连接S的表示选择文科,连接T的表示选择理科

    对于周围的十字,那么就是表示这五个人都选的文科或者理科。

    那我们连一个特殊的点就好了呀,然后文科的十字连接这个点以及这个点周围的点就好了。

    理科同理。

    具体建图看代码,用最小割的思想去理解,就比较简单了。

    代码

    #include<bits/stdc++.h>
    using namespace std;
    const int MAXN=500000,MAXM=500000,inf=1e9;
    struct Edge
    {
        int v,c,f,nx;
        Edge() {}
        Edge(int v,int c,int f,int nx):v(v),c(c),f(f),nx(nx) {}
    } E[MAXM];
    int G[MAXN],cur[MAXN],pre[MAXN],dis[MAXN],gap[MAXN],N,sz;
    void init(int _n)
    {
        N=_n,sz=0; memset(G,-1,sizeof(G[0])*N);
    }
    void link(int u,int v,int c)
    {
        E[sz]=Edge(v,c,0,G[u]); G[u]=sz++;
        E[sz]=Edge(u,0,0,G[v]); G[v]=sz++;
    }
    bool bfs(int S,int T)
    {
        static int Q[MAXN]; memset(dis,-1,sizeof(dis[0])*N);
        dis[S]=0; Q[0]=S;
        for (int h=0,t=1,u,v,it;h<t;++h)
        {
            for (u=Q[h],it=G[u];~it;it=E[it].nx)
            {
                if (dis[v=E[it].v]==-1&&E[it].c>E[it].f)
                {
                    dis[v]=dis[u]+1; Q[t++]=v;
                }
            }
        }
        return dis[T]!=-1;
    }
    int dfs(int u,int T,int low)
    {
        if (u==T) return low;
        int ret=0,tmp,v;
        for (int &it=cur[u];~it&&ret<low;it=E[it].nx)
        {
            if (dis[v=E[it].v]==dis[u]+1&&E[it].c>E[it].f)
            {
                if (tmp=dfs(v,T,min(low-ret,E[it].c-E[it].f)))
                {
                    ret+=tmp; E[it].f+=tmp; E[it^1].f-=tmp;
                }
            }
        }
        if (!ret) dis[u]=-1; return ret;
    }
    int dinic(int S,int T)
    {
        int maxflow=0,tmp;
        while (bfs(S,T))
        {
            memcpy(cur,G,sizeof(G[0])*N);
            while (tmp=dfs(S,T,inf)) maxflow+=tmp;
        }
        return maxflow;
    }
    int n,m;
    int dx[5]={1,-1,0,0,0};
    int dy[5]={0,0,1,-1,0};
    int id(int x,int y){
        return (x-1)*m+y;
    }
    int main(){
        scanf("%d%d",&n,&m);
        int S=0,T=n*m*3+1;
        init(n*m*3+5);
        int ans = 0;
        for(int i=1;i<=n;i++){
            for(int j=1;j<=m;j++){
                int a;scanf("%d",&a);
                ans+=a;
                link(S,id(i,j),a);
            }
        }
        for(int i=1;i<=n;i++){
            for(int j=1;j<=m;j++){
                int a;scanf("%d",&a);
                ans+=a;
                link(id(i,j),T,a);
            }
        }
        for(int i=1;i<=n;i++){
            for(int j=1;j<=m;j++){
                int a;scanf("%d",&a);
                ans+=a;
                link(S,id(i,j)+m*n,a);
                for(int k=0;k<5;k++){
                    int x=dx[k]+i;
                    int y=dy[k]+j;
                    if(x<1||x>n||y<1||y>m)continue;
                    link(id(i,j)+m*n,id(x,y),inf);
                }
            }
        }
        for(int i=1;i<=n;i++){
            for(int j=1;j<=m;j++){
                int a;scanf("%d",&a);
                ans+=a;
                link(id(i,j)+2*m*n,T,a);
                for(int k=0;k<5;k++){
                    int x=dx[k]+i;
                    int y=dy[k]+j;
                    if(x<1||x>n||y<1||y>m)continue;
                    link(id(x,y),id(i,j)+m*n*2,inf);
                }
            }
        }
    
        printf("%d
    ",ans-dinic(S,T));
    }
  • 相关阅读:
    Namenode主节点停止报错 Error: flush failed for required journal
    IntelliJ IDEA2018.3 最新破解方法
    idea 中解决maven 包冲突的问题(maven helper)
    java中的守护线程
    synchronized锁住的是代码还是对象
    maven package,clean,install,compile命令
    设计模式——装饰者模式
    设计模式——观察者模式
    com.alibaba.fastjson.JSON对类对象的序列化与反序列化
    java8 Stream使用案例
  • 原文地址:https://www.cnblogs.com/qscqesze/p/5653494.html
Copyright © 2020-2023  润新知