【BZOJ2127】happiness(最小割)

匿名 (未验证) 提交于 2019-12-02 23:48:02

题目做不完了,明天就要NOI了。

题面

http://darkbzoj.tk/problem/2127

题解

最小割――一个割代表一个方案。

先把所有利益加上,然后用最小割考虑最少的失去的利益。

这道题不用黑白染色,连$S$代表学文,连$T$代表学理。

对于四种情况,列4个方程,5个未知数(对于解的确定有一定的不确定性,那就用好写的解)

#include<cstdio> #include<cstring> #include<iostream> #include<vector> #include<queue> #define ri register int #define N 50000 #define INF 1000000007 #define S 0 #define T (n*m+1) using namespace std;  int n,m,x,sum;  struct graph {   vector<int> to,w;   vector<int> ed[N];   int cur[N],d[N];   void add_edge(int u,int v,int w1) {     to.push_back(v); w.push_back(w1); ed[u].push_back(to.size()-1);     to.push_back(u); w.push_back(0);  ed[v].push_back(to.size()-1);   }   void add_edges(int u,int v,int w1) {     to.push_back(v); w.push_back(w1); ed[u].push_back(to.size()-1);     to.push_back(u); w.push_back(w1);  ed[v].push_back(to.size()-1);   }   bool bfs() {     queue<int> q;     memset(d,0x3f,sizeof(d));     d[0]=0; q.push(0);     while (!q.empty()) {       int x=q.front(); q.pop();       for (ri i=0,l=ed[x].size();i<l;i++) {         int e=ed[x][i];         if (w[e] && d[x]+1<d[to[e]]) {           d[to[e]]=d[x]+1;           q.push(to[e]);         }       }     }     return d[T]<INF;   }   int dfs(int x,int limit) {     if (x==T || !limit) return limit;     int tot=0;     for (ri &i=cur[x];i<ed[x].size();i++) {       int e=ed[x][i];       if (d[to[e]]==d[x]+1 && w[e]) {         int f=dfs(to[e],min(limit,w[e]));         if (!f) continue;         w[e]-=f; w[1^e]+=f;          tot+=f; limit-=f;         if (!limit) return tot;       }     }     return tot;   }   int dinic() {     int ret=0;     while (bfs()) {       memset(cur,0,sizeof(cur));       ret+=dfs(S,INF);     }     return ret;   } } G;  int main(){   cin>>n>>m;   for (ri i=1;i<=n;i++) {     for (ri j=1;j<=m;j++) {       cin>>x; sum+=x;       G.add_edge(S,(i-1)*m+j,x*2);     }   }   for (ri i=1;i<=n;i++) {     for (ri j=1;j<=m;j++) {       cin>>x; sum+=x;       G.add_edge((i-1)*m+j,T,x*2);     }   }   for (ri i=1;i<=n-1;i++) {     for (ri j=1;j<=m;j++) {       cin>>x; sum+=x;       G.add_edge(S,(i-1)*m+j,x);       G.add_edge(S,i*m+j,x);       G.add_edges((i-1)*m+j,i*m+j,x);     }   }   for (ri i=1;i<=n-1;i++) {     for (ri j=1;j<=m;j++) {       cin>>x; sum+=x;       G.add_edge((i-1)*m+j,T,x);       G.add_edge(i*m+j,T,x);       G.add_edges((i-1)*m+j,i*m+j,x);     }   }   for (ri i=1;i<=n;i++) {     for (ri j=1;j<=m-1;j++) {       cin>>x; sum+=x;       G.add_edge(S,(i-1)*m+j,x);       G.add_edge(S,(i-1)*m+j+1,x);       G.add_edges((i-1)*m+j,(i-1)*m+j+1,x);     }   }      for (ri i=1;i<=n;i++) {     for (ri j=1;j<=m-1;j++) {       cin>>x; sum+=x;       G.add_edge((i-1)*m+j,T,x);       G.add_edge((i-1)*m+j+1,T,x);       G.add_edges((i-1)*m+j,(i-1)*m+j+1,x);     }   }      cout<<(2*sum-G.dinic())/2; }
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!