zoukankan      html  css  js  c++  java
  • 【BZOJ】【2127】happiness

    网络流/最小割


      Orz Hzwer

      这题他题解说的比较简略……我手画了个图才明白过来……

      嗯对于每个人选文or理的单独收益大家应该很好理解……连S->i 权值为选文的喜悦值,i->T权值为选理的喜悦值,然后所有的加起来减去最小割即可。

      那么有了相邻的额外喜悦值怎么办呢?首先它跟之前的问题没有冲突,完全可以叠加来做。如上图考虑额外喜悦值,tot=w1+w2,那么我们能得到的最大喜悦值就是tot-最小割,如果我们是两个人选了相同的一科,那割掉的边必然是左边的两条(和为w1)或是右边的两条(和为w2),那如果是选了不同的两科,割掉的就是对角线上的三条边(和为w1+w2),显而易见,这样就可以利用【最小割】来求出最大的喜悦值了。

      这道题我遇到了一个神奇的情况……我跟Hzwer都是写的Dinic,但是我跑下来就有15000ms+,他的程序只有1400ms+,速度是我的十倍啊……

      后来我各种修改然后发现:我加了当前弧优化!这个题目中实际上每个点的边数并不多,所以当前弧优化并不明显,但是每次重建残量网络的时候都要重新初始化一遍当前弧数组cur,这带来了大量的时间浪费……所以就华丽丽地……还好没超时。

      所以对于稀疏图还是不要用当前弧优化了= =尤其是在增广次数比较多的时候……

      1 /**************************************************************
      2     Problem: 2127
      3     User: Tunix
      4     Language: C++
      5     Result: Accepted
      6     Time:15184 ms
      7     Memory:6232 kb
      8 ****************************************************************/
      9  
     10 //BZOJ 2127
     11 #include<vector>
     12 #include<cstdio>
     13 #include<cstring>
     14 #include<cstdlib>
     15 #include<iostream>
     16 #include<algorithm>
     17 #define rep(i,n) for(int i=0;i<n;++i)
     18 #define F(i,j,n) for(int i=j;i<=n;++i)
     19 #define D(i,j,n) for(int i=j;i>=n;--i)
     20 #define pb push_back
     21 using namespace std;
     22 inline int getint(){
     23     int v=0,sign=1; char ch=getchar();
     24     while(ch<'0'||ch>'9'){ if (ch=='-') sign=-1; ch=getchar();}
     25     while(ch>='0'&&ch<='9'){ v=v*10+ch-'0'; ch=getchar();}
     26     return v*sign;
     27 }
     28 const int N=11000,M=300000,INF=~0u>>2;
     29 typedef long long LL;
     30 /******************tamplate*********************/
     31 int n,m,ans,tot,a[110][110],b[110][110];
     32 struct edge{
     33     int from,to,v;
     34 };
     35 inline int pack(int i,int j){return (i-1)*m+j;}
     36 struct Net{
     37     edge E[M];
     38     int head[N],next[M],cnt;
     39     void add(int x,int y,int v){
     40         E[++cnt]=(edge){x,y,v};
     41         next[cnt]=head[x]; head[x]=cnt;
     42         E[++cnt]=(edge){y,x,0};
     43         next[cnt]=head[y]; head[y]=cnt;
     44     }
     45     void add2(int x,int y,int v){
     46         E[++cnt]=(edge){x,y,v};
     47         next[cnt]=head[x]; head[x]=cnt;
     48         E[++cnt]=(edge){y,x,v};
     49         next[cnt]=head[y]; head[y]=cnt;
     50     }
     51     int s,t,cur[N],d[N],Q[N];
     52     void init(){
     53         n=getint();m=getint();
     54         ans=tot=0;cnt=1;
     55         s=0; t=n*m+1;
     56         F(i,1,n) F(j,1,m){
     57             a[i][j]=getint();
     58             tot+=a[i][j]; a[i][j]<<=1;
     59         }
     60         F(i,1,n) F(j,1,m){
     61             b[i][j]=getint();
     62             tot+=b[i][j]; b[i][j]<<=1;
     63         }
     64         int x;
     65         F(i,1,n-1) F(j,1,m){
     66             x=getint(); tot+=x;
     67             a[i][j]+=x; a[i+1][j]+=x;
     68             add2(pack(i,j),pack(i+1,j),x);
     69         }
     70         F(i,1,n-1) F(j,1,m){
     71             x=getint(); tot+=x;
     72             b[i][j]+=x; b[i+1][j]+=x;
     73             add2(pack(i,j),pack(i+1,j),x);
     74         }
     75         F(i,1,n) F(j,1,m-1){
     76             x=getint(); tot+=x;
     77             a[i][j]+=x; a[i][j+1]+=x;
     78             add2(pack(i,j),pack(i,j+1),x);
     79         }
     80         F(i,1,n) F(j,1,m-1){
     81             x=getint(); tot+=x;
     82             b[i][j]+=x; b[i][j+1]+=x;
     83             add2(pack(i,j),pack(i,j+1),x);
     84         }
     85         F(i,1,n) F(j,1,m){
     86             add(s,pack(i,j),a[i][j]);
     87             add(pack(i,j),t,b[i][j]);
     88         }
     89     }
     90     bool mklevel(){
     91         memset(d,-1,sizeof d);
     92         d[s]=0;
     93         int l=0,r=-1;
     94         Q[++r]=s;
     95         while(l<=r){
     96             int x=Q[l++];
     97             for(int i=head[x];i;i=next[i])
     98                 if (d[E[i].to]==-1 && E[i].v){
     99                     d[E[i].to]=d[x]+1;
    100                     Q[++r]=E[i].to;
    101                 }
    102         }
    103         return d[t]!=-1;
    104     }
    105     int dfs(int x,int a){
    106         if (x==t||a==0) return a;
    107         int flow=0;
    108         for(int &i=cur[x];i && flow<a;i=next[i])
    109             if (d[E[i].to]==d[x]+1 && E[i].v){
    110                 int f=dfs(E[i].to,min(a-flow,E[i].v));
    111                 E[i].v-=f;
    112                 E[i^1].v+=f;
    113                 flow+=f;
    114             }
    115         return flow;
    116     }
    117     int Dinic(){
    118         int flow=0;
    119         while(mklevel()){
    120             F(i,s,t) cur[i]=head[i];
    121             flow+=dfs(s,INF);
    122         }
    123         return flow;
    124     }
    125 }G1;
    126 int main(){
    127 #ifndef ONLINE_JUDGE
    128     freopen("2127.in","r",stdin);
    129     freopen("2127.out","w",stdout);
    130 #endif
    131     G1.init();
    132     printf("%d
    ",tot-(G1.Dinic()>>1));
    133     return 0;
    134 }
    View Code 时间超长……
      1 /**************************************************************
      2     Problem: 2127
      3     User: Tunix
      4     Language: C++
      5     Result: Accepted
      6     Time:1332 ms
      7     Memory:4600 kb
      8 ****************************************************************/
      9  
     10 //BZOJ 2127
     11 #include<cstdio>
     12 #include<cstring>
     13 #include<algorithm>
     14 #define rep(n,m) for(int i=1;i<=n;i++)for(int j=1;j<=m;j++)
     15 #define FOR for(int i=1;i<=n;i++)for(int j=1;j<=m;j++)
     16 using namespace std;
     17 inline int getint(){
     18     int v=0,sign=1; char ch=getchar();
     19     while(ch<'0'||ch>'9'){ if (ch=='-') sign=-1; ch=getchar();}
     20     while(ch>='0'&&ch<='9'){ v=v*10+ch-'0'; ch=getchar();}
     21     return v*sign;
     22 }
     23 const int N=10005,M=300000,INF=~0u>>2;
     24 typedef long long LL;
     25 /******************tamplate*********************/
     26 int n,m,ans,tot,a[101][101],b[101][101],pack[101][101];
     27 struct edge{
     28     int to,v;
     29 };
     30 edge E[M];
     31 int head[N],next[M],cnt;
     32 void ins(int x,int y,int v){
     33     ++cnt; E[cnt].to=y; E[cnt].v=v;
     34     next[cnt]=head[x]; head[x]=cnt;
     35 }
     36 void add(int x,int y,int v){
     37     ins(x,y,v); ins(y,x,0);
     38 }
     39 void add2(int x,int y,int v){
     40     ins(x,y,v); ins(y,x,v);
     41 }
     42 int s,t,cur[N],d[N],Q[N];
     43 void init(){
     44     n=getint();m=getint();
     45     ans=tot=0;cnt=1;
     46     s=0; t=n*m+1;
     47     FOR a[i][j]=getint(),tot+=a[i][j],a[i][j]<<=1;
     48     FOR b[i][j]=getint(),tot+=b[i][j],b[i][j]<<=1;
     49     FOR pack[i][j]=(i-1)*m+j;
     50     int x;
     51     rep(n-1,m){
     52         x=getint(); tot+=x;
     53         a[i][j]+=x; a[i+1][j]+=x;
     54         add2(pack[i][j],pack[i+1][j],x);
     55     }
     56     rep(n-1,m){
     57         x=getint(); tot+=x;
     58         b[i][j]+=x; b[i+1][j]+=x;
     59         add2(pack[i][j],pack[i+1][j],x);
     60     }
     61     rep(n,m-1){
     62         x=getint(); tot+=x;
     63         a[i][j]+=x; a[i][j+1]+=x;
     64         add2(pack[i][j],pack[i][j+1],x);
     65     }
     66     rep(n,m-1){
     67         x=getint(); tot+=x;
     68         b[i][j]+=x; b[i][j+1]+=x;
     69         add2(pack[i][j],pack[i][j+1],x);
     70     }
     71     FOR{
     72         add(s,pack[i][j],a[i][j]);
     73         add(pack[i][j],t,b[i][j]);
     74     }
     75 }
     76 bool mklevel(){
     77     memset(d,-1,sizeof d);
     78     d[s]=0;
     79     int l=0,r=-1;
     80     Q[++r]=s;
     81     while(l<=r){
     82         int x=Q[l++];
     83         for(int i=head[x];i;i=next[i])
     84             if (d[E[i].to]==-1 && E[i].v){
     85                 d[E[i].to]=d[x]+1;
     86                 Q[++r]=E[i].to;
     87             }
     88     }
     89     return d[t]!=-1;
     90 }
     91 int dfs(int x,int a){
     92     if (x==t||a==0) return a;
     93     int flow=0;
     94     for(int i=head[x];i && flow<a;i=next[i])
     95         if (d[E[i].to]==d[x]+1 && E[i].v){
     96             int f=dfs(E[i].to,min(a-flow,E[i].v));
     97             E[i].v-=f;
     98             E[i^1].v+=f;
     99             flow+=f;
    100         }
    101     if (!flow) d[x]=-1;
    102     return flow;
    103 }
    104 void Dinic(){
    105     while(mklevel()) ans+=dfs(s,INF);
    106 }
    107 int main(){
    108 #ifndef ONLINE_JUDGE
    109     freopen("2127.in","r",stdin);
    110     freopen("2127.out","w",stdout);
    111 #endif
    112     init(); Dinic();
    113     printf("%d
    ",tot-(ans>>1));
    114     return 0;
    115 }
    116 
    View Code 速度超快~

    2127: happiness

    Time Limit: 51 Sec  Memory Limit: 259 MB
    Submit: 923  Solved: 444
    [Submit][Status][Discuss]

    Description

    高 一一班的座位表是个n*m的矩阵,经过一个学期的相处,每个同学和前后左右相邻的同学互相成为了好朋友。这学期要分文理科了,每个同学对于选择文科与理科 有着自己的喜悦值,而一对好朋友如果能同时选文科或者理科,那么他们又将收获一些喜悦值。作为计算机竞赛教练的scp大老板,想知道如何分配可以使得全班 的喜悦值总和最大。

    Input

    第一行两个正整数n,m。接下来 是六个矩阵第一个矩阵为n行m列 此矩阵的第i行第j列的数字表示座位在第i行第j列的同学选择文科获得的喜悦值。第二个矩阵为n行m列 此矩阵的第i行第j列的数字表示座位在第i行第j列的同学选择理科获得的喜悦值。第三个矩阵为n-1行m列 此矩阵的第i行第j列的数字表示座位在第i行第j列的同学与第i+1行第j列的同学同时选择文科获得的额外喜悦值。第四个矩阵为n-1行m列 此矩阵的第i行第j列的数字表示座位在第i行第j列的同学与第i+1行第j列的同学同时选择理科获得的额外喜悦值。第五个矩阵为n行m-1列 此矩阵的第i行第j列的数字表示座位在第i行第j列的同学与第i行第j+1列的同学同时选择文科获得的额外喜悦值。第六个矩阵为n行m-1列 此矩阵的第i行第j列的数字表示座位在第i行第j列的同学与第i行第j+1列的同学同时选择理科获得的额外喜悦值。

    Output

    输出一个整数,表示喜悦值总和的最大值

    Sample Input

    1 2
    1 1
    100 110
    1
    1000

    Sample Output

    1210
    【样例说明】
    两人都选理,则获得100+110+1000的喜悦值。
    【数据规模】
    对于100%以内的数据,n,m<=100 所有喜悦值均为小于等于5000的非负整数

    HINT

    Source

    [Submit][Status][Discuss]
  • 相关阅读:
    批量新增百万条数据 十百万条数据
    sqlserver 组内排序
    EF ++属性会更新实体
    Entity Framework Core: A second operation started on this context before a previous operation completed
    abp Cannot access a disposed object. A common cause of this error is disposing
    abp xunit Can not register IHostingEnvironment. It should be a non-abstract class. If not, it should be registered before.”
    hangfire enqueued but not processing(hangfire 定时任务入队列但不执行)
    EF 更新实体 The instance of entity type 'BabyEvent' cannot be tracked because another instance
    datatable to entiy list 不支持可空类型和枚举类型
    webapi 设置不显示接口到swaggerUI
  • 原文地址:https://www.cnblogs.com/Tunix/p/4338011.html
Copyright © 2011-2022 走看看