【最小割】BZOJ3894-文理分科

【题目大意】

给定一个m*n的矩阵,每个格子的人可以学文或者学理,学文和学理各有一个满意度,如果以某人为中心的十字内所有人都学文或者学理还会得到一个额外满意度,求最大满意度之和。

【思路】

发现这道题那么久(比划——)之前交过没A。强迫症先水过填个坑。懒得写题解了,都是套路。思路类似于以前的小M的农作物,戳:

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cstring>
  4 #include<algorithm>
  5 #include<queue>
  6 #include<vector>
  7 #define S 0
  8 #define T m*n*3+1 
  9 using namespace std;
 10 const int INF=0x7fffffff;
 11 const int MAXN=3*100*100+50;
 12 struct node
 13 {
 14     int to,pos,cap;
 15 };
 16 int m,n,ans; 
 17 vector<node> E[MAXN];
 18 int dis[MAXN];
 19 int dx[4]={1,-1,0,0};
 20 int dy[4]={0,0,1,-1};
 21  
 22 void addedge(int u,int v,int w)
 23 {
 24     E[u].push_back((node){v,E[v].size(),w});
 25     E[v].push_back((node){u,E[u].size()-1,0});
 26 }
 27  
 28 bool bfs()
 29 {
 30     memset(dis,-1,sizeof(dis));
 31     queue<int> que;
 32     while (!que.empty()) que.pop(); 
 33     que.push(S);
 34     dis[S]=0;
 35     while (!que.empty())
 36     {
 37         int head=que.front();que.pop();
 38         if (head==T) return true;  
 39         for (int i=0;i<E[head].size();i++)
 40         {
 41             node tmp=E[head][i];
 42             if (dis[tmp.to]==-1 && tmp.cap)
 43             {
 44                 dis[tmp.to]=dis[head]+1;
 45                 que.push(tmp.to);
 46             }
 47         }
 48     }
 49     return false;
 50 }
 51  
 52 int dfs(int s,int e,int f)
 53 {
 54     if (s==e) return f;
 55     int ret=0;
 56     for (int i=0;i<E[s].size();i++)
 57     {
 58         node &tmp=E[s][i];
 59         if (dis[tmp.to]==dis[s]+1 && tmp.cap)
 60         {
 61             int delta=dfs(tmp.to,e,min(f,tmp.cap));
 62             if (delta>0)
 63             {
 64                 tmp.cap-=delta;
 65                 E[tmp.to][tmp.pos].cap+=delta;
 66                 f-=delta;
 67                 ret+=delta;
 68                 if (f==0) return ret;
 69             }
 70             else dis[tmp.to]=-1;
 71         }
 72     } 
 73     return ret;
 74 }
 75  
 76 void dinic()
 77 {
 78     while (bfs())
 79     {
 80         int f=dfs(S,T,INF);
 81         if (f) ans-=f;else break;
 82     }
 83     printf("%d\n",ans);
 84 }
 85 
 86 void init()
 87 {
 88     scanf("%d%d",&n,&m);
 89     ans=0;
 90     for (int i=1;i<=n;i++)
 91         for (int j=1;j<=m;j++)
 92         {
 93             int now=(i-1)*m+j,art;
 94             scanf("%d",&art);
 95             addedge(S,now,art);
 96             ans+=art;
 97         }
 98     for (int i=1;i<=n;i++)
 99         for (int j=1;j<=m;j++)
100         {
101             int now=(i-1)*m+j,science;
102             scanf("%d",&science);
103             addedge(now,T,science);
104             ans+=science;
105         }
106         
107     int cnt=m*n,same;
108     for (int i=1;i<=n;i++)
109         for (int j=1;j<=m;j++)
110         {
111             ++cnt;
112             scanf("%d",&same);
113             addedge(S,cnt,same);
114             ans+=same;
115             addedge(cnt,(i-1)*m+j,INF);
116             for (int k=0;k<4;k++)
117             {
118                 int nowx=i+dx[k],nowy=j+dy[k];
119                 if (nowx>=1 && nowx<=n && nowy>=1 && nowy<=m)
120                     addedge(cnt,(nowx-1)*m+nowy,INF);
121             }
122         }
123     for (int i=1;i<=n;i++)
124         for (int j=1;j<=m;j++)
125         {
126             ++cnt;
127             scanf("%d",&same);
128             addedge(cnt,T,same);
129             ans+=same;
130             addedge((i-1)*m+j,cnt,INF);
131             for (int k=0;k<4;k++)
132             {
133                 int nowx=i+dx[k],nowy=j+dy[k];
134                 if (nowx>=1 && nowx<=n && nowy>=1 && nowy<=m)
135                     addedge((nowx-1)*m+nowy,cnt,INF);
136             }
137         }
138 }
139  
140 int main()
141 {
142     init();
143     dinic();
144     return 0;
145 }

 

posted @ 2016-08-15 15:23  iiyiyi  阅读(166)  评论(0编辑  收藏  举报