zoukankan      html  css  js  c++  java
  • 题解 文理分科

    题面

    解析

    首先,分析题目,

    因为每个人要么选文科,要么选理科。

    所以这道题可以用最小割来解决。

    先设文科为S,理科为T(反过来也没区别),

    再将每个人与文科,理科都连起来,

    流量就为满意值,

    那么,肯定得割掉一条边,

    然后,就要处理相同科目满意值了,

    其实,只要把相邻的四个人和中间的一个人连到一个点上,

    再把那个点连到理科就行了(文科也一样但要另外建一个点)。

    最后求最小割就可以了!

    上AC代码:

    #include<bits/stdc++.h>
    using namespace std;
    
    inline int read(){
        int sum=0,f=1;char ch=getchar();
        while(ch>'9' || ch<'0'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0' && ch<='9'){sum=sum*10+ch-'0';ch=getchar();}
        return f*sum;
    }
    
    const int INF=0x3f3f3f3f;
    struct hh{
        int to,next,v;
    }e[1000001];
    int n,m,si,ti,sum;
    int a[101][101],s[101][101],sa[101][101],ss[101][101];
    int id[101][101];
    int head[100001],cnt=1;
    int d[100001];
    int dx[4]={0,0,1,-1};
    int dy[4]={-1,1,0,0};
    
    void ppre(){
        int kk=0;
        for(int i=1;i<=n;i++)
            for(int j=1;j<=m;j++) id[i][j]=++kk;
    }
    
    void add(int x,int y,int v){
        e[++cnt].to=head[x];
        e[cnt].next=y;
        e[cnt].v=v;
        head[x]=cnt;
    }
    
    bool bfs(){
        memset(d,0,sizeof(d));
        queue <int> que;
        que.push(si);
        d[si]=1;
        while(!que.empty()){
            int x=que.front();
            que.pop();   
            for(int i=head[x];i;i=e[i].to){
                int k=e[i].next;
                if(!e[i].v||d[k]) continue;
                d[k]=d[x]+1;        
                que.push(k);
            }
        }
        return d[ti];
    }
    
    int dfs(int x,int mi){
        if(x==ti||!mi) return mi;
        int flow=0;
        for(int i=head[x];i;i=e[i].to){
            int k=e[i].next;
            if(!e[i].v||d[k]!=d[x]+1) continue;
            int ret=dfs(k,min(mi,e[i].v));
            e[i].v-=ret;e[i^1].v+=ret;
            flow+=ret;mi-=ret;
            if(!mi) break;
        }
        if(mi) d[x]=-1;
        return flow;
    }
    
    void DINIC(){
        int ans=sum;
        while(bfs()){
            int ret=dfs(si,INF);
            sum-=ret;
        }
        printf("%d
    ",sum);
    }
    
    int main(){
    //    freopen("divide.in","r",stdin);    
    //    freopen("divide.out","w",stdout);
        n=read();m=read();
            ppre();
        si=n*m*3+10;ti=n*m*3+20;
        for(int i=1;i<=n;i++)
            for(int j=1;j<=m;j++)
                a[i][j]=read(),sum+=a[i][j];
        for(int i=1;i<=n;i++)
            for(int j=1;j<=m;j++)
                s[i][j]=read(),sum+=s[i][j];
        for(int i=1;i<=n;i++)
            for(int j=1;j<=m;j++)
                sa[i][j]=read(),sum+=sa[i][j];
        for(int i=1;i<=n;i++)
            for(int j=1;j<=m;j++)
                ss[i][j]=read(),sum+=ss[i][j];
        for(int i=1;i<=n;i++){
            for(int j=1;j<=m;j++){
                add(si,id[i][j],s[i][j]);
                add(id[i][j],si,0);
                add(id[i][j],ti,a[i][j]);
                add(ti,id[i][j],0);
            }
        }
        for(int i=1;i<=n;i++){
            for(int j=1;j<=m;j++){
                int l=id[i][j]+n*m;
                add(l,ti,sa[i][j]);add(ti,l,0);
                add(id[i][j],l,INF);add(l,id[i][j],0);
                for(int k=0;k<4;k++){
                    int x=i+dx[k],y=j+dy[k];
                    if(x<=0||y<=0||x>n||y>m) continue;
                    add(id[x][y],l,INF);add(l,id[x][y],0);
                }
            }
        }
        for(int i=1;i<=n;i++){
            for(int j=1;j<=m;j++){
                int l=id[i][j]+n*m*2;
                add(si,l,ss[i][j]);add(l,si,0);
                add(l,id[i][j],INF);add(id[i][j],l,0);
    //            add(id[i][j],l,INF);add(l,id[i][j],0);
                for(int k=0;k<4;k++){
                    int x=i+dx[k],y=j+dy[k];
                    if(x<=0||y<=0||x>n||y>m) continue;
                    add(l,id[x][y],INF);add(id[x][y],l,0);
                }
            }
        }
        DINIC();
        return 0;
        
    }
  • 相关阅读:
    删除使用RMAN命令备份的文件
    查看.Net Framework版本的方法(zz)
    c# Foreach last (zz)
    Visual Studio 2008 QFE (zz)
    打印机的接口
    牛人的PENTAX单反之路
    我新进的宾得K10D机器和镜头
    买车险要有足额第三者责任险
    谈谈P家的SUPERTAKUAMR
    硬盘接口总结
  • 原文地址:https://www.cnblogs.com/zsq259/p/10528374.html
Copyright © 2011-2022 走看看