• 【bzoj3894】文理分科 网路流


    【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 58 13 15 4
    11 3 8 11
    11 18 6 51 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
     
      1 #include<cstring>
      2 #include<cmath>
      3 #include<iostream>
      4 #include<algorithm>
      5 #include<cstdio>
      6 #include<queue>
      7 
      8 #define inf 1000000007
      9 #define N 30007
     10 #define M 1000007
     11 using namespace std;
     12 const int xx[5]={0,1,-1,0,0};
     13 const int yy[5]={0,0,0,1,-1};
     14 inline int read()
     15 {
     16     int x=0,f=1;char ch=getchar();
     17     while(ch<'0'||ch>'9'){if (ch=='-')f=-1;ch=getchar();}
     18     while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
     19     return x*f;
     20 }
     21 
     22 int n,m,S,T,ans;
     23 int cnt=1,hed[N],cur[N],nxt[M],rea[M],val[M];
     24 int dis[N];
     25 
     26 void add(int u,int v,int w)
     27 {
     28     nxt[++cnt]=hed[u];
     29     hed[u]=cnt;
     30     rea[cnt]=v;
     31     val[cnt]=w;
     32 }
     33 void add_two_edge(int u,int v,int w)
     34 {
     35     add(u,v,w),add(v,u,0);
     36 }
     37 bool bfs()
     38 {
     39     for (int i=S;i<=T;i++)dis[i]=-1;
     40     dis[S]=0;queue<int>q;q.push(S);
     41     while(!q.empty())
     42     {
     43         int u=q.front();q.pop();
     44         for (int i=hed[u];i!=-1;i=nxt[i])
     45         {
     46             int v=rea[i],fee=val[i];
     47             if (dis[v]!=-1||fee==0)continue;
     48             dis[v]=dis[u]+1;
     49             if (v==T)return 1;
     50             q.push(v);
     51         }
     52     }
     53     return 0;
     54 }
     55 int dfs(int u,int MX)
     56 {
     57     if (u==T||MX==0) return MX;
     58     int res=0;
     59     for (int i=cur[u];i!=-1;i=nxt[i])
     60     {
     61         int v=rea[i],fee=val[i];
     62         if (dis[v]!=dis[u]+1)continue;
     63         int x=dfs(v,min(MX,fee));
     64         cur[u]=i,res+=x,MX-=x;
     65         val[i]-=x,val[i^1]+=x;
     66         if (!MX)break;
     67     }
     68     if (!res) dis[u]=-1;
     69     return res;
     70 }
     71 int dinic()
     72 {
     73     int res=0;
     74     while(bfs())
     75     {
     76     //    cout<<1<<endl;
     77         for (int i=S;i<=T;i++)cur[i]=hed[i];
     78         res+=dfs(S,inf);
     79     }
     80     return res;
     81 }
     82 int main()
     83 {
     84     memset(hed,-1,sizeof(hed));
     85     n=read(),m=read(),S=0,T=n*m*3+1;
     86     for (int i=1;i<=n;i++)
     87         for (int j=1;j<=m;j++)
     88         {
     89             int x=read();ans+=x;
     90             add_two_edge(S,(i-1)*m+j,x);
     91         }
     92     for (int i=1;i<=n;i++)
     93         for (int j=1;j<=m;j++)
     94         {
     95             int x=read();ans+=x;
     96             add_two_edge((i-1)*m+j,T,x);
     97         }
     98     for (int i=1;i<=n;i++)
     99         for (int j=1;j<=m;j++)
    100         {
    101             int x=read();ans+=x;
    102             for (int k=0;k<5;k++)
    103             {
    104                 int lx=i+xx[k],ly=j+yy[k];
    105                 if (lx<1||lx>n||ly<1||ly>m)continue;
    106                 add_two_edge((i-1)*m+j+n*m,(lx-1)*m+ly,inf);
    107             }
    108             add_two_edge(S,(i-1)*m+j+n*m,x);
    109         }
    110     for (int i=1;i<=n;i++)
    111         for (int j=1;j<=m;j++)
    112         {
    113             int x=read();ans+=x;
    114             for (int k=0;k<5;k++)
    115             {
    116                 int lx=i+xx[k],ly=j+yy[k];
    117                 if (lx<1||lx>n||ly<1||ly>m)continue;
    118                 add_two_edge((lx-1)*m+ly,(i-1)*m+j+2*n*m,inf);
    119             }
    120             add_two_edge((i-1)*m+j+2*n*m,T,x);
    121         }
    122     ans-=dinic();
    123     printf("%d
    ",ans);
    124 }
  • 相关阅读:
    动态内存开辟(一)
    结构体,联合体,枚举,typedef
    练习使用C++的string类
    WIN10 + Qt 5.14(MSVC 2017,32bit) + APP项目(minGW-7.3.0 32bit)+glog
    扫雷游戏
    最小栈实现
    快速排序算法
    c++语句(循环)
    C++ 存储类
    C++ 运算符
  • 原文地址:https://www.cnblogs.com/fengzhiyuan/p/8287313.html
Copyright © 2020-2023  润新知