[BZOJ2127]happiness-[网络流-最小割]
Description
Solution
按照最小割的思路考虑。
根据题意,当两个人都选文(理),需要砍掉两个人都选理(文)的加成;如果两个人选的不一样,就要都砍掉。
这是一个网络流建模的套路:
如图。为了防止出现分数,我们把每条边边权*2。
最后用总的喜悦值去掉网络流大小即可。(记得除以2)
Code
#include<iostream> #include<cstdio> #include<cstring> #include<cmath> #include<queue> using namespace std; const int inf=1e9; int h[10020],tot=0; struct pas{int x,y,nxt,w,op,cost;}g[300100]; int dep[10020],S,T; queue<int>q; struct DINIC{ bool bfs() { int x; memset(dep,0,sizeof(dep));dep[S]=1; while (!q.empty()) q.pop(); q.push(S); while (!q.empty()) { x=q.front();q.pop(); for (int i=h[x];i;i=g[i].nxt) if (!dep[g[i].y]&&g[i].w) { dep[g[i].y]=dep[x]+1; q.push(g[i].y); if (g[i].y==T) return 1; } } return 0; } int dfs(int x,int flow) { if (x==T||(!flow))return flow; int temp=0,js; for (int i=h[x];i;i=g[i].nxt) if (dep[g[i].y]==dep[x]+1&&g[i].w) { js=dfs(g[i].y,min(flow,g[i].w)); if (js) { g[i].w-=js; g[g[i].op].w+=js; temp+=js; flow-=js; if (!flow) return temp; } } if (!temp) dep[x]=0; return temp; } int dinic() { int ans=0; while (bfs()) ans+=dfs(S,inf); return ans; } }D; void add(int x,int y,int w) { g[++tot].x=x;g[tot].y=y;g[tot].w=w;g[tot].nxt=h[x];g[tot].op=tot+1;h[x]=tot; g[++tot].x=y;g[tot].y=x;g[tot].w=0;g[tot].nxt=h[y];g[tot].op=tot-1;h[y]=tot; } int n,m,sum; int art[110][110],sci[110][110]; int row_art[110][110],row_sci[110][110]; int col_art[110][110],col_sci[110][110];//col-column int id(int x,int y){return (x-1)*m+y;} int main() { scanf("%d%d",&n,&m); S=0;T=id(n,m)+1; for (int i=1;i<=n;i++) for (int j=1;j<=m;j++) { scanf("%d",&art[i][j]); sum+=art[i][j]; art[i][j]*=2; } for (int i=1;i<=n;i++) for (int j=1;j<=m;j++) { scanf("%d",&sci[i][j]); sum+=sci[i][j]; sci[i][j]*=2; } for (int i=1;i<n;i++) for (int j=1;j<=m;j++) { scanf("%d",&row_art[i][j]);sum+=row_art[i][j]; art[i][j]+=row_art[i][j]; art[i+1][j]+=row_art[i][j]; } for (int i=1;i<n;i++) for (int j=1;j<=m;j++) { scanf("%d",&row_sci[i][j]);sum+=row_sci[i][j]; sci[i][j]+=row_sci[i][j]; sci[i+1][j]+=row_sci[i][j]; add(id(i,j),id(i+1,j),row_art[i][j]+row_sci[i][j]); add(id(i+1,j),id(i,j),row_art[i][j]+row_sci[i][j]); } for (int i=1;i<=n;i++) for (int j=1;j<m;j++) { scanf("%d",&col_art[i][j]);sum+=col_art[i][j]; art[i][j]+=col_art[i][j]; art[i][j+1]+=col_art[i][j]; } for (int i=1;i<=n;i++) for (int j=1;j<m;j++) { scanf("%d",&col_sci[i][j]);sum+=col_sci[i][j]; sci[i][j]+=col_sci[i][j]; sci[i][j+1]+=col_sci[i][j]; add(id(i,j),id(i,j+1),col_art[i][j]+col_sci[i][j]); add(id(i,j+1),id(i,j),col_art[i][j]+col_sci[i][j]); } for (int i=1;i<=n;i++) for (int j=1;j<=m;j++) { add(S,id(i,j),art[i][j]); add(id(i,j),T,sci[i][j]); } printf("%d",(sum*2-D.dinic())/2); }