【BZOJ】【3894】文理分科

网络流/最小割


  rausen大爷太神辣~作为一个蒟蒻还是搬运题解吧……

很明显的一道网络流题。。

首先把所有值的加起来,再减掉网络流最小割值就好了,问题就是如何建图。这貌似也是考了好多次了的。。。

把每个人抽象成一个点p,则

先是S向p连边,流量为选文科的高兴值,p向T连边,流量为选理科的高兴值。

然后是same的条件,对每个人新建两个点p1, p2

S向p1连边,流量为文科same的高兴值,p1向相邻点和自己的p连边,流量为inf

p2相T连边,流量为理科same的高兴值,相邻点和自己的p向p2连边,流量为inf

然后跑一下网络流就好了(蒟蒻tot = 1没写调了半天还以为建图错了= =b)

  1 /**************************************************************
  2     Problem: 3894
  3     User: Tunix
  4     Language: C++
  5     Result: Accepted
  6     Time:2404 ms
  7     Memory:40340 kb
  8 ****************************************************************/
  9  
 10 //BZOJ 3894
 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=1e6+10,M=2000010,INF=~0u>>2;
 29 typedef long long LL;
 30 /******************tamplate*********************/
 31 const int fx[]={0,1,0,-1,0},
 32           fy[]={1,0,-1,0,0};
 33 int n,m,tot,ans;
 34 struct edge{int to,v;};
 35 inline int pack(int i,int j){return (i-1)*m+j;}
 36 #define FOR F(i,1,n)F(j,1,m)
 37 struct Net{
 38     edge E[M];
 39     int head[N],next[M],cnt;
 40     void ins(int x,int y,int v){
 41         E[++cnt]=(edge){y,v};
 42         next[cnt]=head[x]; head[x]=cnt;
 43     }
 44     void add(int x,int y,int v){
 45         ins(x,y,v); ins(y,x,0);
 46     }
 47     int s,t,cur[N],d[N],Q[N];
 48     bool mklevel(){
 49         memset(d,-1,sizeof d);
 50         d[s]=0;
 51         int l=0,r=-1;
 52         Q[++r]=s;
 53         while(l<=r){
 54             int x=Q[l++];
 55             for(int i=head[x];i;i=next[i])
 56                 if (d[E[i].to]==-1 && E[i].v){
 57                     d[E[i].to]=d[x]+1;
 58                     Q[++r]=E[i].to;
 59                 }
 60         }
 61         return d[t]!=-1;
 62     }
 63     int dfs(int x,int a){
 64         if (x==t) return a;
 65         int flow=0;
 66         for(int i=head[x];i && flow<a;i=next[i])
 67             if (E[i].v && d[E[i].to]==d[x]+1){
 68                 int f=dfs(E[i].to,min(a-flow,E[i].v));
 69                 E[i].v-=f;
 70                 E[i^1].v+=f;
 71                 flow+=f;
 72             }
 73         if (!flow) d[x]=-1;
 74         return flow;
 75     }
 76     void Dinic(){
 77         while(mklevel()) ans-=dfs(s,INF);
 78     }
 79     void init(){
 80         n=getint(); m=getint(); cnt=1;
 81         tot=n*m; s=0; t=tot*3+1;
 82         int x=0;
 83         FOR{
 84             x=getint(); ans+=x;
 85             add(s,pack(i,j),x);
 86         }
 87         FOR{
 88             x=getint(); ans+=x;
 89             add(pack(i,j),t,x);
 90         }
 91         FOR{
 92             x=getint(); ans+=x;
 93             add(s,tot+pack(i,j),x);
 94             F(k,0,4){
 95                 int tx=i+fx[k],ty=j+fy[k];
 96                 if(tx<1||ty<1||tx>n||ty>m)continue;
 97                 add(tot+pack(i,j),pack(tx,ty),INF);
 98             }
 99         }
100         FOR{
101             x=getint(); ans+=x;
102             add(tot*2+pack(i,j),t,x);
103             F(k,0,4){
104                 int tx=i+fx[k],ty=j+fy[k];
105                 if(tx<1||ty<1||tx>n||ty>m)continue;
106                 add(pack(tx,ty),tot*2+pack(i,j),INF);
107             }
108         }
109         Dinic();
110         printf("%d\n",ans);
111     }
112 }G1;
113  
114 int main(){
115 #ifndef ONLINE_JUDGE
116     freopen("3894.in","r",stdin);
117     freopen("3894.out","w",stdout);
118 #endif
119     G1.init();
120     return 0;
121 }
View Code

 

posted @ 2015-03-31 23:30  Tunix  阅读(199)  评论(0编辑  收藏  举报