ACM模板库

ACM模板库


有源汇上下界最小费用流(可行流与最大流)

<pre><code class="language-cpp">#include&lt;bits/stdc++.h&gt; using namespace std; #define endl '\n' #define IOS ios::sync_with_stdio(false); cin.tie(0), cout.tie(0) typedef long long LL; const int maxn = 2e5 + 5; const int INF = 0x3f3f3f3f; struct Edge{ int u,v,nxt,f,w; }edge[maxn&lt;&lt;1]; int head[255],cnt = -1; int w[255]; int sb[55][55],sw[55][55]; int L[55],R[55],l[55],r[55]; inline void add_edge(int u,int v,int f,int w){ edge[++cnt] = {u,v,head[u],f,w}; head[u] = cnt; edge[++cnt] = {v,u,head[v],0,-w}; head[v] = cnt; } inline void init(){ memset(head,-1,sizeof(head)); cnt = -1; } int dis[255],flow[255],vis[255],pre[255],last[255]; bool spfa(int s,int t){ memset(dis,0x3f,sizeof(dis)); memset(flow,0x3f,sizeof(flow)); memset(vis,0,sizeof(vis)); queue&lt;int&gt; q; q.push(s); vis[s] = 1,dis[s] = 0,pre[t] = -1; while(!q.empty()){ int u = q.front(); q.pop(); vis[u] = 0; for(int i = head[u]; ~i; i = edge[i].nxt){ Edge &amp;e = edge[i]; if(e.f &gt; 0 &amp;&amp; dis[e.v] &gt; dis[u] + e.w){ dis[e.v] = dis[u] + e.w; pre[e.v] = u; last[e.v] = i; flow[e.v] = min(flow[u],e.f); if(!vis[e.v]){ vis[e.v] = 1; q.push(e.v); } } } } return pre[t] != -1; } int maxflow,mincost; int MCMF(int s,int t){ maxflow = mincost = 0; while(spfa(s,t)){ int u = t; maxflow += flow[t]; mincost += flow[t] * dis[t]; while(u != s){ edge[last[u]].f -= flow[t]; edge[last[u]^1].f += flow[t]; u = pre[u]; } } return maxflow; } int main(){ IOS; init(); int n,m; cin &gt;&gt; n &gt;&gt; m; int s = 0, t = n + m + 1; int ss = t + 1,tt = ss + 1; for(int i = 1; i &lt;= n; ++i){ for(int j = 1; j &lt;= m; ++j){ cin &gt;&gt; sb[i][j]; } } for(int i = 1; i &lt;= n; ++i){ for(int j = 1; j &lt;= m; ++j){ cin &gt;&gt; sw[i][j]; } } //下面输入上下限 for(int i = 1; i &lt;= n; ++i){ cin &gt;&gt; l[i] &gt;&gt; r[i]; } for(int i = 1; i &lt;= m; ++i){ cin &gt;&gt; L[i] &gt;&gt; R[i]; } //下面是建边求可行流 for(int i = 1; i &lt;= n; ++i){ add_edge(s, i, r[i]-l[i], 0); w[s] -= l[i]; w[i] += l[i]; } for(int i = 1; i &lt;= m; ++i){ add_edge(i + n, t, R[i] - L[i], 0); w[i+n] -= L[i]; w[t] += L[i]; } for(int i = 1; i &lt;= n; ++i){ for(int j = 1; j &lt;= m; ++j){ add_edge(j + n, i, 1, sw[i][j]); add_edge(i, j + n, 1, sb[i][j]);//最小循环流满流处理 } } //下面是补全流 long long sum = 0; for(int i = 0; i &lt;= t; ++i){ if(w[i] &gt; 0){ add_edge(ss, i, w[i], 0); sum += w[i]; }else if(w[i] &lt;= 0){ add_edge(i, tt, -w[i], 0); } } add_edge(t, s, INF, 0); //上下限没有负限制的时候不需要加这个add(s,t,INF,0),而这里不加只能通过牛客69%的数据) add_edge(s, t, INF, 0); MCMF(ss,tt); //MCMF(s,t); cout &lt;&lt;mincost &lt;&lt; endl; return 0; } </code></pre>

页面列表

ITEM_HTML