Orz Hzwer

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

【BZOJ】【2127】happiness

  嗯对于每个人选文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\n",tot-(G1.Dinic()>>1));
133     return 0;
134 }
View Code 时间超长……

相关文章: