bzoj1497 最小割
题意: 新的技术正冲击着手机通讯市场,对于各大运营商来说,这既是机遇,更是挑战。THU集团旗下的CS&T通讯公司在新一代通讯技术血战的前夜,需要做太多的准备工作,仅就站址选择一项,就需要完成前期市场研究、站址勘测、最优化等项目。在前期市场调查和站址勘测之后,公司得到了一共N个可以作为通讯信号中转站的地址,而由于这些地址的地理位置差异,在不同的地方建造通讯中转站需要投入的成本也是不一样的,所幸在前期调查之后这些都是已知数据:建立第i个通讯中转站需要的成本为Pi(≤i≤N)。另外公司调查得出了所有期望中的用户群,一共M个。关于第i个用户群的信息概括为Ai, Bi和Ci:这些用户会使用中转站Ai和中转站Bi进行通讯,公司可以获益Ci。(≤i≤M, ≤Ai, Bi≤N) THU集团的CS&T公司可以有选择的建立一些中转站(投入成本),为一些用户提供服务并获得收益(获益之和)。那么如何选择最终建立的中转站才能让公司的净获利最大呢?(净获利 = 获益之和 - 投入成本之和) Input 输入文件中第一行有两个正整数N和M 。第二行中有N个整数描述每一个通讯中转站的建立成本,依次为P1, P2, …, PN 。以下M行,第(i + )行的三个数Ai, Bi和Ci描述第i个用户群的信息。所有变量的含义可以参见题目描述。 Output 你的程序只要向输出文件输出一个整数,表示公司可以得到的最大净获利。
题意
据说是一个很经典的最小割模型 最大权闭合子图
我们将源点和用户连接一条收益的边,用户和两个中转站连接一条INF的边,中转站和汇点连接一条花费的边。
首先最理想的情况就是只拿收益不拿成本,但是这显然是不可能的,所以我们建的图实际上是一个满收益成本的图。
我们可以割用户和源点的边:放弃收益
或者割中转站和汇点的边:加上成本。
所以整个图的最小割就是最大收益 - 最小成本。
#include <map>
#include <set>
#include <ctime>
#include <cmath>
#include <queue>
#include <stack>
#include <vector>
#include <string>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <sstream>
#include <iostream>
#include <algorithm>
#include <functional>
using namespace std;
inline int read(){int now=;register char c=getchar();for(;!isdigit(c);c=getchar());
for(;isdigit(c);now=now*+c-'',c=getchar());return now;}
#define For(i, x, y) for(int i=x;i<=y;i++)
#define _For(i, x, y) for(int i=x;i>=y;i--)
#define Mem(f, x) memset(f,x,sizeof(f))
#define Sca(x) scanf("%d", &x)
#define Sca2(x,y) scanf("%d%d",&x,&y)
#define Sca3(x,y,z) scanf("%d%d%d",&x,&y,&z)
#define Scl(x) scanf("%lld",&x);
#define Pri(x) printf("%d\n", x)
#define Prl(x) printf("%lld\n",x);
#define CLR(u) for(int i=0;i<=N;i++)u[i].clear();
#define LL long long
#define ULL unsigned long long
#define mp make_pair
#define PII pair<int,int>
#define PIL pair<int,long long>
#define PLL pair<long long,long long>
#define pb push_back
#define fi first
#define se second
typedef vector<int> VI;
const double eps = 1e-;
const int maxn = 2e5 + ;
const int maxm = 4e5 + ;
const int INF = 0x3f3f3f3f;
const int mod = 1e9 + ;
int N,M,K;
struct Dinic{
struct Edge{
int from,to,cap,flow,nxt;
Edge() {}
Edge(int u,int v,int c,int f,int n):from(u),to(v),cap(c),flow(f),nxt(n) {}
}edge[maxm];
int n,s,t,E,head[maxn];
bool vis[maxn];
int d[maxn],cur[maxn];
inline void AddEdge(int f,int t,int c){
edge[++E] = Edge(f,t,c,,head[f]);
head[f] = E;
edge[++E] = Edge(t,f,,,head[t]);
head[t] = E;
}
inline void Init(int n,int s,int t){
this -> n = n; E = -;
this -> s = s; head[s] = -;
this -> t = t; head[t] = -;
for(int i = ; i <= n ; i ++) head[i] = -;
} inline bool BFS(){
memset(vis,,sizeof(vis));
queue<int>Q;
d[s] = ;vis[s] = ;
for(Q.push(s);!Q.empty();){
int x = Q.front(); Q.pop();
for(int nxt,i = head[x];~i;i = nxt){
Edge &e = edge[i]; nxt = e.nxt;
if(vis[e.to] || e.cap <= e.flow) continue;
vis[e.to] = ;
d[e.to] = d[x] + ;
Q.push(e.to);
}
}
return vis[t];
} inline int DFS(const int &x,int a){
if(x == t || a == ) return a;
int flow = ,f,nxt;
for(int &i = cur[x]; ~i; i = nxt){
Edge &e = edge[i]; nxt = e.nxt;
if(d[x] + != d[e.to]) continue;
f = DFS(e.to,min(a,e.cap - e.flow));
if(f <= ) continue;
e.flow += f;
edge[i ^ ].flow -= f;
flow += f; a -= f;
if(!a) break;
}
return flow;
}
inline int maxFlow(){return maxFlow(s,t);}
inline int maxFlow(int s,int t){
int flow = ;
for(;BFS();){
for(int i = ;i <= n ; i ++) cur[i] = head[i];
flow += DFS(s,INF);
}
return flow;
}
}g; int main()
{
Sca2(N,M);
g.Init(N + M + ,N + M + ,);
For(i,,N){
int x = read();
g.AddEdge(i,,x);
}
int sum = ;
For(i,,M){
int u,v,w;
Sca3(u,v,w); sum += w;
g.AddEdge(i + N,u,INF);
g.AddEdge(i + N,v,INF);
g.AddEdge(N + M + ,i + N,w);
}
Pri(sum - g.maxFlow());
#ifdef VSCode
system("pause");
#endif
return ;
}
bzoj1497 最小割的更多相关文章
- [bzoj1497][NOI2006]最大获利_网络流_最小割
最大获利 bzoj-1497 题目大意:可以建立一个点,花费一定的代价:将已经建立的两个点之间连边,得到一定收益.有些节点之间是不允许连边的. 注释:1<=点数<=5,000,1<= ...
- BZOJ1497 [NOI2006]最大获利 网络流 最小割 SAP
原文链接http://www.cnblogs.com/zhouzhendong/p/8371052.html 题目传送门 - BZOJ1497 题意概括 有n个站要被建立. 建立第i个站的花费为pi. ...
- 【BZOJ1497】[NOI2006]最大获利 最小割
裸的最小割,很经典的模型. 建图:要求总收益-总成本最大,那么将每条弧与源点相连,流量为成本,每个收益与汇点相连,流量为收益,然后每条弧与它所能到达的收益相连,流量为inf. 与源点相连的是未被选中的 ...
- BZOJ1497: [NOI2006]最大获利[最小割 最大闭合子图]
1497: [NOI2006]最大获利 Time Limit: 5 Sec Memory Limit: 64 MBSubmit: 4375 Solved: 2142[Submit][Status] ...
- bzoj1497(最小割)
传送门:最大获利 题意:建立n个中转站,每个花费P[i],有m个用户,使用Ai和Bi中转站可获利Ci,问最终建立哪几个中转站使获利最大? 分析:根据最大权闭合图建图,用户群和中转站为带权的点集,用户群 ...
- bzoj1497: [NOI2006]最大获利(最小割)
传送门 第一眼看去:好难 第二眼:不就是个裸的最大权闭合子图么…… 我们从源点向所有用户连边,容量为收益,用户向自己的中转站连边,容量为INF,中转站向汇点连边,容量为费用 那么总收益-最小割就是答案 ...
- 二分图&网络流&最小割等问题的总结
二分图基础: 最大匹配:匈牙利算法 最小点覆盖=最大匹配 最小边覆盖=总节点数-最大匹配 最大独立集=点数-最大匹配 网络流: 技巧: 1.拆点为边,即一个点有限制,可将其转化为边 BZOJ1066, ...
- 一类最小割bzoj2127,bzoj2132 bzoj3438
思考一下我们接触的最小割问题 最小割的基本问题(可能会和图论的知识相结合,比如bzoj1266,bzoj1797) 最大权闭合图(bzoj1497) 最大点权覆盖集,最大点权独立集(bzoj1324) ...
- BZOJ 1391: [Ceoi2008]order [最小割]
1391: [Ceoi2008]order Time Limit: 10 Sec Memory Limit: 64 MBSubmit: 1509 Solved: 460[Submit][Statu ...
随机推荐
- Data Science With R In Visual Studio
R Projects Similar to Python, when we installed the data science tools we get an “R” section in our ...
- spring事务 将多个connection放到一个线程中
spring事务 将多个connection放到一个线程中
- Cmder使用ls中文显示乱码解决方案
操作系统:Windows 7 旗舰版 Cmder:1.3.2 默认配置不支持使用ls显示中文命名的文件列表. 解决方法: 按下Win+Alt+P打开设置. 在StartUp - Environment ...
- visual studio 显示引用关系 作者更改项
visual studio 2017中,每个类或者方法顶部会显示此方法的引用关系或者作者更改项:这个功能极大了提高了我们代码的定位效率:不过有时候却发现每一行代码都有,会增加我们屏幕显示内容,有时候看 ...
- C - A Simple Problem with Integers POJ - 3468 线段树模版(区间查询区间修改)
参考qsc大佬的视频 太强惹 先膜一下 视频在b站 直接搜线段树即可 #include<cstdio> using namespace std; ; int n,a[maxn]; stru ...
- BZOJ4755 [JSOI2016]扭动的回文串 【后缀数组】【manacher】
题目分析: 我写了史上最丑的后缀数组,怎么办? 首先manacher一遍两个串,这样只用考虑第三问.用$作为间隔符拼接两个串,把第一个串翻转.枚举回文中心,取最长的回文串,对于剩下的部分利用LCP匹配 ...
- 【UOJ347】【WC2018】通道 边分治 虚树 DP
题目大意 给你三棵树,点数都是\(n\).求 \[ \max_{i,j}d_1(i,j)+d_2(i,j)+d_3(i,j) \] 其中\(d_k(i,j)\)是在第\(k\)棵数中\(i,j\)两点 ...
- 《Hands-On Machine Learning with Scikit-Learn&TensorFlow》mnist数据集错误及解决方案
最近在看这本书看到Chapter 3.Classification,是关于mnist数据集的分类,里面有个代码是 from sklearn.datasets import fetch_mldata m ...
- Android 可展开列表组件 ExpandableListView
ExpandableListView 是ListView的子类,它把应用中的列表项分为几组,每组里可包含多个列表项. 所显示的列表项应该由ExpandableListAdapter 接口提供,实现Ex ...
- HDU6341 Let Sudoku Rotate (杭电多校4J)
给一个由4*4个4*4的小格组成数独,这些数独是由一个块逆时针旋转得来的,所以要还原的话就模拟出顺时针的过程,先把里面的字母转化成数字,然后从第一个块开始枚举,每个dfs和之前枚举的已经满足条件的块, ...