zoukankan      html  css  js  c++  java
  • bzoj3894: 文理分科

    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

    样例说明

    1表示选择文科,0表示选择理科,方案如下:

    1  0  0  1

    0  1  0  0

    1  0  0  0

     

    N,M<=100,读入数据均<=500

    题解:

    二元组建图:http://www.cnblogs.com/chenyushuo/p/5146626.html 

    这看上去是一个多元关系,但我们可以转化为二元关系

    我们对每个节点x0新建两个点x1,x2分别表示x0周围是否都是选文和是否都选理,然后有以下四种二元关系

    x0选文且x1为是,那么有v1的收入

    x0选理且x2为是,那么有v2的收入

    x1为是,与x0相邻的点必须选文,如果选了理,则造成inf的代价

    x2为是,与x0相邻的点必须选理,如果选了文,则造成inf的代价

    然后二元组建图即可

    code:

     1 #include<cstdio>
     2 #include<iostream>
     3 #include<cmath>
     4 #include<cstring>
     5 #include<algorithm>
     6 #define maxn 30005
     7 #define maxm 1200000
     8 #define inf 1061109567
     9 using namespace std;
    10 char ch;
    11 bool ok;
    12 void read(int &x){
    13     for (ok=0,ch=getchar();!isdigit(ch);ch=getchar()) if (ch=='-') ok=1;
    14     for (x=0;isdigit(ch);x=x*10+ch-'0',ch=getchar());
    15     if (ok) x=-x;
    16 }
    17 int n,m,sum,pos[105][105][3],x;
    18 struct flow{
    19     int s,t,tot,now[maxn],son[maxm],pre[maxm],val[maxm];
    20     int dis[maxn],head,tail,list[maxn];
    21     bool bo[maxn];
    22     void init(){s=0,t=n*m*3+1,tot=1,memset(now,0,sizeof(now));}
    23     void put(int a,int b,int c){pre[++tot]=now[a],now[a]=tot,son[tot]=b,val[tot]=c;}
    24     void add(int a,int b,int c){put(a,b,c),put(b,a,0);}
    25     bool bfs(){
    26         memset(bo,0,sizeof(bo));
    27         head=0,tail=1,list[1]=s,dis[s]=0,bo[s]=1;
    28         while (head<tail){
    29             int u=list[++head];
    30             for (int p=now[u],v=son[p];p;p=pre[p],v=son[p])
    31                 if (val[p]&&!bo[v]) bo[v]=1,dis[v]=dis[u]+1,list[++tail]=v;
    32         }
    33         return bo[t];
    34     }
    35     int dfs(int u,int rest){
    36         if (u==t) return rest;
    37         int ans=0;
    38         for (int p=now[u],v=son[p];p&&rest;p=pre[p],v=son[p])
    39             if (val[p]&&dis[v]==dis[u]+1){
    40                 int d=dfs(v,min(rest,val[p]));
    41                 val[p]-=d,val[p^1]+=d,ans+=d,rest-=d;
    42             }
    43         if (!ans) dis[u]=-1;
    44         return ans;
    45     }
    46     int dinic(){
    47         int ans=0;
    48         while (bfs()) ans+=dfs(s,inf);
    49         return ans;
    50     }
    51 }f;
    52 const int dx[4]={1,0,-1,0};
    53 const int dy[4]={0,1,0,-1};
    54 int main(){
    55     read(n),read(m),f.init();
    56     for (int i=1;i<=n;i++) for (int j=1;j<=m;j++)
    57         pos[i][j][0]=(i-1)*m+j,pos[i][j][1]=pos[i][j][0]+n*m,pos[i][j][2]=pos[i][j][1]+n*m;
    58     for (int i=1;i<=n;i++) for (int j=1;j<=m;j++) read(x),sum+=x,f.add(pos[i][j][0],f.t,x<<1);
    59     for (int i=1;i<=n;i++) for (int j=1;j<=m;j++) read(x),sum+=x,f.add(f.s,pos[i][j][0],x<<1);
    60     for (int i=1;i<=n;i++) for (int j=1;j<=m;j++){
    61         read(x),sum+=(x<<1);
    62         f.add(pos[i][j][0],pos[i][j][1],x),f.add(pos[i][j][1],pos[i][j][0],x);
    63         f.add(f.s,pos[i][j][0],x),f.add(f.s,pos[i][j][1],x);
    64         f.add(pos[i][j][0],f.t,x<<1),f.add(pos[i][j][1],f.t,x<<1);
    65     }
    66     for (int i=1;i<=n;i++) for (int j=1;j<=m;j++) for (int k=0;k<4;k++){
    67         int x=i+dx[k],y=j+dy[k];
    68         if (x<=0||x>n||y<=0||y>m) continue;
    69         f.add(pos[x][y][0],pos[i][j][1],inf);
    70     }
    71     for (int i=1;i<=n;i++) for (int j=1;j<=m;j++){
    72         read(x),sum+=(x<<1);
    73         f.add(pos[i][j][0],pos[i][j][2],x),f.add(pos[i][j][2],pos[i][j][0],x);
    74         f.add(pos[i][j][0],f.t,x),f.add(pos[i][j][2],f.t,x);
    75         f.add(f.s,pos[i][j][0],x<<1),f.add(f.s,pos[i][j][2],x<<1);
    76     }
    77     for (int i=1;i<=n;i++) for (int j=1;j<=m;j++) for (int k=0;k<4;k++){
    78         int x=i+dx[k],y=j+dy[k];
    79         if (x<=0||x>n||y<=0||y>m) continue;
    80         f.add(pos[i][j][2],pos[x][y][0],inf);
    81     }
    82     printf("%d
    ",sum-(f.dinic()>>1));
    83     return 0;
    84 }
  • 相关阅读:
    【C#】.net 发送get/post请求
    【C#】什么时候使用virtual什么时候使用abstract
    【C#】为什么有可能会被多个线程修改的对象要加线程锁
    【ADO.NET】 使用通用数据库操作类Database (SQL Server)
    【ADO.NET】 基础 (SQL Server)
    【前端】模拟微信上传图片(带预览,支持预览gif)
    【前端】Html5浏览器缓存 sessionStorage 与 localStorage
    【C#】.net 导出Excel功能
    【前端】jQurey Plugin
    【c#】对象转json字符串/字符串转Json对象
  • 原文地址:https://www.cnblogs.com/chenyushuo/p/5147375.html
Copyright © 2011-2022 走看看