bzoj2132【圈地计划】
思路:
一开始以为和为了博多一样,两边连一样的,后来发现中间连负边的话根本不会割,即割断两块收益为负,所以WA的起飞……
正解是先黑白染色,每个点和它周围的点连边方式不同。对于黑点A,S-->A表示商业区的价值,A-->T表示工业区的价值,白点相反,对于相邻的情况,边权表示相邻的价值和,这样割断相当于选择同一用途,代价为正。
1 #include <map> 2 #include <set> 3 #include <cmath> 4 #include <queue> 5 #include <stack> 6 #include <cstdio> 7 #include <string> 8 #include <vector> 9 #include <cstring> 10 #include <complex> 11 #include <cstdlib> 12 #include <iostream> 13 #include <algorithm> 14 #define rg register 15 #define ll long long 16 using namespace std; 17 18 inline int gi() 19 { 20 rg int r = 0; rg bool b = 1; rg char c = getchar(); 21 while ((c < '0' || c > '9') && c != '-') c = getchar(); 22 if (c == '-') b = 0; 23 while (c >= '0' && c <= '9') { r = (r << 1) + (r << 3) + c - '0', c = getchar(); } 24 if (b) return r; return -r; 25 } 26 27 const int inf = 2e8+5, N = 105, M = 5e5+1; 28 int n,m,num,S,T; 29 int dx[]={0,0,-1,1},dy[]={-1,1,0,0},dep[N*N],f[N*N],c[N][N]; 30 bool col[N][N]; 31 queue <int> q; 32 struct Edge 33 { 34 int to,nx,cap; 35 }eg[M]; 36 37 inline void add(int x,int y,int z) 38 { 39 eg[++num]=(Edge){y,f[x],z}, f[x]=num; 40 } 41 42 inline void link(int x,int y,int z) 43 { 44 add(x,y,z), add(y,x,0); 45 } 46 47 inline int dfs(int o,int flow) 48 { 49 if (o == T || !flow) return flow; 50 rg int to,cap,fl,tmp,i; 51 fl=0; 52 for (i=f[o]; i; i=eg[i].nx) 53 { 54 to=eg[i].to, cap=eg[i].cap; 55 if (dep[o] != dep[to]-1 || cap <= 0) 56 continue; 57 tmp=dfs(to,min(flow,cap)); 58 if (!tmp) continue; 59 fl+=tmp, flow-=tmp; 60 eg[i].cap-=tmp, eg[i^1].cap+=tmp; 61 if (!flow) break; 62 } 63 if (!fl) dep[o]=0; 64 return fl; 65 } 66 67 inline int bfs() 68 { 69 memset(dep,0,sizeof(dep)); 70 rg int o,to,cap,i; 71 q.push(S); dep[S]=1; 72 while (!q.empty()) 73 { 74 o=q.front(), q.pop(); 75 for (i=f[o]; i; i=eg[i].nx) 76 { 77 to=eg[i].to, cap=eg[i].cap; 78 if (dep[to] || cap <= 0) 79 continue; 80 dep[to]=dep[o]+1, q.push(to); 81 } 82 } 83 return dep[T]; 84 } 85 86 inline int dinic() 87 { 88 rg int flow; 89 flow=0; 90 while (bfs()) flow+=dfs(S,inf); 91 return flow; 92 } 93 94 int main() 95 { 96 rg int i,j,k,x,y,dis,ans; 97 n=gi(), m=gi(); 98 ans=S=0, T=n*m+1, num=1; 99 for (i=1; i<=n; ++i) 100 for (j=1; j<=m; ++j) 101 if ((i+j)&1) 102 col[i][j]=1; 103 for (i=1; i<=n; ++i) 104 for (j=1; j<=m; ++j) 105 { 106 dis=gi(), ans+=dis; 107 if (col[i][j]) 108 link(S,(i-1)*m+j,dis); 109 else 110 link((i-1)*m+j,T,dis); 111 } 112 113 for (i=1; i<=n; ++i) 114 for (j=1; j<=m; ++j) 115 { 116 dis=gi(), ans+=dis; 117 if (col[i][j]) 118 link((i-1)*m+j,T,dis); 119 else 120 link(S,(i-1)*m+j,dis); 121 } 122 for (i=1; i<=n; ++i) for (j=1; j<=m; ++j) c[i][j]=gi(); 123 for (i=1; i<=n;++i) 124 for (j=1; j<=m; ++j) 125 { 126 if (!col[i][j]) continue; 127 for (k=0; k<4; ++k) 128 { 129 x=i+dx[k], y=j+dy[k]; 130 if (x > n || x < 1 || y > m || y < 1) 131 continue; 132 add((i-1)*m+j,(x-1)*m+y,c[i][j]+c[x][y]); 133 add((x-1)*m+y,(i-1)*m+j,c[i][j]+c[x][y]); 134 ans+=c[i][j]+c[x][y]; 135 } 136 } 137 printf("%d\n",ans-dinic()); 138 return 0; 139 }