最大权闭合子图的模型;今天才发现dinic板子是一直挂的……

Description

新的技术正冲击着手机通讯市场,对于各大运营商来说,这既是机遇,更是挑战。THU集团旗下的CS&T通讯公司在新一代通讯技术血战的前夜,需要做太多的准备工作,仅就站址选择一项,就需要完成前期市场研究、站址勘测、最优化等项目。在前期市场调查和站址勘测之后,公司得到了一共N个可以作为通讯信号中转站的地址,而由于这些地址的地理位置差异,在不同的地方建造通讯中转站需要投入的成本也是不一样的,所幸在前期调查之后这些都是已知数据:建立第i个通讯中转站需要的成本为Pi(1≤i≤N)。另外公司调查得出了所有期望中的用户群,一共M个。关于第i个用户群的信息概括为Ai, Bi和Ci:这些用户会使用中转站Ai和中转站Bi进行通讯,公司可以获益Ci。(1≤i≤M, 1≤Ai, Bi≤N) THU集团的CS&T公司可以有选择的建立一些中转站(投入成本),为一些用户提供服务并获得收益(获益之和)。那么如何选择最终建立的中转站才能让公司的净获利最大呢?(净获利 = 获益之和 - 投入成本之和)

Input

输入文件中第一行有两个正整数N和M 。第二行中有N个整数描述每一个通讯中转站的建立成本,依次为P1, P2, …, PN 。以下M行,第(i + 2)行的三个数Ai, Bi和Ci描述第i个用户群的信息。所有变量的含义可以参见题目描述。

Output

你的程序只要向输出文件输出一个整数,表示公司可以得到的最大净获利。

Sample Input

5 5
1 2 3 4 5
1 2 3
2 3 4
1 3 3
1 4 2
4 5 3

Sample Output

4

HINT

【样例说明】选择建立1、2、3号中转站,则需要投入成本6,获利为10,因此得到最大收益4。【评分方法】本题没有部分分,你的程序的输出只有和我们的答案完全一致才能获得满分,否则不得分。【数据规模和约定】 80%的数据中:N≤200,M≤1 000。 100%的数据中:N≤5 000,M≤50 000,0≤Ci≤100,0≤Pi≤100。


题目分析

最早来看这题的时候,建出来的图同时带了点权和边权,弄得稀里糊涂……

这里需要把每一个需求抽象出来,向需要的基站建立拓扑关系,接下去的事就是最大权闭合子图的板子了。

这一种大概是最大权闭合子图的建图套路吧。

 #include<bits/stdc++.h>
const int maxn = ;
const int maxm = ;
const int maxNode = ;
const int INF = 2e9; struct Edge
{
int u,v,f,c;
Edge(int a=, int b=, int c=, int d=):u(a),v(b),f(c),c(d) {}
}edges[maxm];
int n,m,ans;
int edgeTot,head[maxNode],cur[maxNode],nxt[maxm],S,T;
int lv[maxNode]; int read()
{
char ch = getchar();
int num = , fl = ;
for (; !isdigit(ch); ch=getchar())
if (ch=='-') fl = -;
for (; isdigit(ch); ch=getchar())
num = (num<<)+(num<<)+ch-;
return num*fl;
}
void addedge(int u, int v, int c)
{
edges[edgeTot] = Edge(u, v, , c), nxt[edgeTot] = head[u], head[u] = edgeTot, ++edgeTot;
edges[edgeTot] = Edge(v, u, , ), nxt[edgeTot] = head[v], head[v] = edgeTot, ++edgeTot;
}
bool buildLevel()
{
std::queue<int> q;
memset(lv, , sizeof lv);
lv[S] = , q.push(S);
for (int i=; i<=T; i++) cur[i] = head[i];
for (int tmp; q.size(); )
{
tmp = q.front(), q.pop();
for (int i=head[tmp]; i!=-; i=nxt[i])
{
int v = edges[i].v;
if (!lv[v]&&edges[i].f < edges[i].c){
lv[v] = lv[tmp]+, q.push(v);
if (v==T) return true;
}
}
}
return false;
}
int fndPath(int x, int lim)
{
int sum = ;
if (x==T||!lim) return lim;
for (int i=cur[x]; i!=-&&sum <= lim; i=nxt[i])
{
int v = edges[i].v, val;
if (lv[x]+==lv[v]&&edges[i].f < edges[i].c){
if ((val = fndPath(v, std::min(lim-sum, edges[i].c-edges[i].f)))){
edges[i].f += val, edges[i^].f -= val;
sum += val;
}else lv[v] = -;
}
}
cur[x] = head[x];
return sum;
}
int dinic()
{
int ret = , val;
while (buildLevel())
while ((val = fndPath(S, INF))) ret += val;
return ret;
}
int main()
{
memset(head, -, sizeof head);
n = read(), m = read(), S = n+m+, T = S+;
for (int i=; i<=n; i++) addedge(m+i, T, read());
for (int i=; i<=m; i++)
{
int u = read()+m, v = read()+m, c = read();
addedge(i, u, INF);
addedge(i, v, INF);
addedge(S, i, c);
ans += c;
}
printf("%d\n",ans-dinic());
return ;
}

END

最新文章

  1. wdcp的安装扩展模块
  2. TeamViewer“试用期已到期”解决方法
  3. UVA11149 矩阵快速幂
  4. 使用VAssistX给文件和函数添加注释-2015.12.31
  5. Flask-SQLALchemy查询
  6. java excel导出
  7. python如何将指定路径下的某类型文件,返回一个树形结构体,让前端显示为树形的目录结构
  8. P1092 虫食算
  9. 【转】用Linux命令行获取本机外网IP地址
  10. Appium移动自动化测试(三)--安装Android模拟器(建议直接连手机,跳过此步)
  11. Spring WebFlux开门迎客,却来了一位特殊客人
  12. jquery监听textarea内容变化
  13. 第9条:try-with-resources优于try-finally
  14. 迁移桌面程序到MS Store(5)——.NET Standard
  15. 装饰页面decorators.xml
  16. hdu 2546 饭卡【01背包】
  17. Ubuntu 增加全新硬盘 分区及开机自动挂载
  18. python 写入execl记录
  19. HDFS NameNode HA 部署文档
  20. Spring JMX之一:使用JMX管理Spring Bean

热门文章

  1. ES6简述
  2. Python内建函数二
  3. HDU6442(二项式)
  4. 批量插入,update
  5. Prime Count 求大区间素数个数
  6. poj 2406 Power Strings 后缀数组解法
  7. ngnix集群产生的问题
  8. 一、Postgresql的基本操作
  9. 1143 纪念品分组 2007年NOIP全国联赛普及组
  10. 用配置文件方式启动mongodb集群