bzoj2127happiness
题意:
高一一班的座位表是个n*m的矩阵。这学期要分文理科了,每个同学对于选择文科与理科有着自己的喜悦值,而相邻两个同学如果能同时选文科或者理科,那么他们又将收获一些喜悦值。求全班的喜悦值总和的最大值。
题解:
题解太难写,转黄学长的吧(我太弱)
“
利用最小割考虑。
对于原图中所有相邻的两个人A,B,我们建边:
s->A:cost[A文]+c[文][A][B]/2,s->B:cost[B文]+c[文][A][B]/2;
A->t:cost[A理]+c[理][A][B]/2,B->t:costB[理]+c[理][A][B]/2;
A<–>B:c[文][A][B]/2+c[理][A][B]/2
”
注意里面的AB之间的无向边是一门玄学,当它满载时表示AB分属不同集合,而且无向边不需要反向边(要反向边也行),用的是普通图的插边方式。还有那些除以2只要将cost*2,然后最后求出来的最小割除以2就行。最后答案是所有收益和减最小割。
代码:
1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm> 4 #include <queue> 5 #define inc(i,j,k) for(int i=j;i<=k;i++) 6 #define visit(i,j) for(int i=g[j];i!=-1;i=es[i].n) 7 #define INF 0x3fffffff 8 using namespace std; 9 10 struct e{int t,c,n;}; e es[500000]; int ess,g[20000]; 11 inline void pe(int f,int t,int c){es[++ess]=(e){t,c,g[f]}; g[f]=ess; es[++ess]=(e){f,0,g[t]}; g[t]=ess;} 12 inline void pe2(int f,int t,int c){es[++ess]=(e){t,c,g[f]}; g[f]=ess; es[++ess]=(e){f,c,g[t]}; g[t]=ess;} 13 inline void init(){ess=-1; memset(g,-1,sizeof(g));} 14 queue <int> q; int h[20000]; 15 bool bfs(int s,int t){ 16 while(! q.empty())q.pop(); memset(h,-1,sizeof(h)); q.push(s); h[s]=0; 17 while(! q.empty()){ 18 int x=q.front(); q.pop(); 19 visit(i,x)if(es[i].c&&h[es[i].t]==-1){h[es[i].t]=h[x]+1; q.push(es[i].t);} 20 } 21 if(h[t]==-1)return 0;else return 1; 22 } 23 int dfs(int x,int t,int f){ 24 if(x==t)return f; int u=0; 25 visit(i,x)if(es[i].c&&h[es[i].t]==h[x]+1){ 26 int w=dfs(es[i].t,t,min(f,es[i].c)); 27 f-=w; u+=w; es[i].c-=w; es[i^1].c+=w; if(f==0)return u; 28 } 29 if(!u)h[x]=-1; return u; 30 } 31 int dinic(int s,int t){int f=0; while(bfs(s,t))f+=dfs(s,t,INF); return f;} 32 int a1[200][200],a2[200][200],tot,n,m,s,t; 33 inline int cg(int x,int y){return (x-1)*m+y;} 34 int main(){ 35 scanf("%d%d",&n,&m); tot=0; 36 inc(i,1,n)inc(j,1,m)scanf("%d",&a1[i][j]),tot+=a1[i][j],a1[i][j]<<=1; 37 inc(i,1,n)inc(j,1,m)scanf("%d",&a2[i][j]),tot+=a2[i][j],a2[i][j]<<=1; 38 s=0; t=n*m+1; init(); 39 inc(i,1,n-1)inc(j,1,m){ 40 int x; scanf("%d",&x); a1[i][j]+=x; a1[i+1][j]+=x; tot+=x; pe2(cg(i,j),cg(i+1,j),x); 41 } 42 inc(i,1,n-1)inc(j,1,m){ 43 int x; scanf("%d",&x); a2[i][j]+=x; a2[i+1][j]+=x; tot+=x; pe2(cg(i,j),cg(i+1,j),x); 44 } 45 inc(i,1,n)inc(j,1,m-1){ 46 int x; scanf("%d",&x); a1[i][j]+=x; a1[i][j+1]+=x; tot+=x; pe2(cg(i,j),cg(i,j+1),x); 47 } 48 inc(i,1,n)inc(j,1,m-1){ 49 int x; scanf("%d",&x); a2[i][j]+=x; a2[i][j+1]+=x; tot+=x; pe2(cg(i,j),cg(i,j+1),x); 50 } 51 inc(i,1,n)inc(j,1,m){pe(s,cg(i,j),a1[i][j]); pe(cg(i,j),t,a2[i][j]);} 52 printf("%d",tot-(dinic(s,t)>>1)); 53 return 0; 54 }
20160324