http://acm.hdu.edu.cn/showproblem.php?pid=3879

http://www.lydsy.com/JudgeOnline/problem.php?id=1497

题意:给出n个点m条边,其中每个点有一个权值代表修建这个点需要耗费的钱,然后m条边里面,代表如果两个修建好的点相连的话,那么可以得到一点利润。求最大的获利。

思路:和BZOJ 1497是同一道题目。学习最大权闭合图的题目,看了一下不清楚应该怎么建图,然后只好搜一个论文来看看。http://wenku.baidu.com/view/6507a6fe2cc58bd63186bdaf.html

建图:将S与n个点相连,权值为点权,将m条边当成点与T相连,权值为边权,边的两个顶点分别再和化成点的边相连,权值为INF。

闭合图可以解决一些依赖关系,例如这道题目需要有两个顶点才可以得到一条边,边是依赖于两个顶点的形成的。

于是网络是这样的:S->站的点->边的点->T。

我们对这个网络得到的一个割 = 选择的站的花费 + 未选择的边的利润(也可以看作损失的利润),显然这个割集越小越好,即最小割。我们要求的是答案 = 选择的边的利润 - 选择的站的利润。

那么我们一开始可以先累加得到一个选择所有边的利润tot,那么恰好tot - 最小割 = 选择所有边的利润 - 未选择边的利润 - 选择的站的花费 = 选择的边的利润 - 选择的站的利润 = 答案。

所以跑一遍最大流后就用tot - 最大流就可以得到答案了。

记得边的数组要开大一点。

 #include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
using namespace std;
#define INF 0x3f3f3f3f
#define N 60010
#define M 350010 // 30w不过
struct Edge {
int u, v, nxt, cap;
Edge () {}
Edge (int u, int v, int nxt, int cap) : u(u), v(v), nxt(nxt), cap(cap) {}
} edge[M];
int head[N], tot, S, T, cur[N], dis[N], gap[N], pre[N]; void Add(int u, int v, int cap) {
edge[tot] = Edge(u, v, head[u], cap); head[u] = tot++;
edge[tot] = Edge(v, u, head[v], ); head[v] = tot++;
} void BFS() {
queue<int> que;
que.push(T);
memset(dis, INF, sizeof(dis));
memset(gap, , sizeof(gap));
gap[]++; dis[T] = ;
while(!que.empty()) {
int u = que.front(); que.pop();
for(int i = head[u]; ~i; i = edge[i].nxt) {
if(dis[edge[i].v] != INF) continue;
dis[edge[i].v] = dis[u] + ;
gap[dis[edge[i].v]]++;
que.push(edge[i].v);
}
}
} int ISAP(int n) {
BFS();
memcpy(cur, head, sizeof(cur));
int u = pre[S] = S, flow, ans = , index, i;
while(dis[S] < n) {
if(u == T) {
flow = INF;
for(i = S; i != T; i = edge[cur[i]].v)
if(flow > edge[cur[i]].cap) flow = edge[cur[i]].cap, index = i;
for(i = S; i != T; i = edge[cur[i]].v)
edge[cur[i]].cap -= flow, edge[cur[i]^].cap += flow;
u = index; ans += flow;
}
for(i = cur[u]; ~i; i = edge[i].nxt) if(edge[i].cap && dis[edge[i].v] + == dis[u]) break;
if(~i) { cur[u] = i; pre[edge[i].v] = u; u = edge[i].v; }
else {
if(--gap[dis[u]] == ) break;
int md = n + ;
for(i = head[u]; ~i; i = edge[i].nxt)
if(edge[i].cap && dis[edge[i].v] < md) md = dis[edge[i].v], cur[u] = i;
gap[dis[u] = md + ]++;
u = pre[u];
}
}
return ans;
} int main() {
int n, m;
while(~scanf("%d%d", &n, &m)) {
memset(head, -, sizeof(head));
tot = ; S = ; T = n + m + ;
for(int i = ; i <= n; i++) {
int w; scanf("%d", &w);
Add(S, i, w); // 源点和站点相连
}
int tot = ;
for(int i = ; i <= m; i++) {
int a, b, c;
scanf("%d%d%d",&a, &b, &c);
tot += c; // 选择边的利润和
Add(i + n, T, c); // 边的点和汇点相连
Add(a, i + n, INF);
Add(b, i + n, INF);
}
printf("%d\n", tot - ISAP(T + ));
}
return ;
}

HDU 3879 && BZOJ 1497:Base Station && 最大获利 (最大权闭合图)的更多相关文章

  1. hdu - 4971 - A simple brute force problem.(最大权闭合图)

    题意:n(n <= 20)个项目,m(m <= 50)个技术问题,做完一个项目能够有收益profit (<= 1000),做完一个项目必须解决对应的技术问题,解决一个技术问题须要付出 ...

  2. HDU 4971 - A simple brute force problem【最大权闭合图】

    有n(20)个工程,完成每个工程获得收益是p[i],m(50)个需要解决的难题,解决每个难题花费是c[i] 要完成第i个工程,需要先解决ki个问题,具体哪些问题,输入会给出 每个难题之间可能有依赖关系 ...

  3. hdu 3061 hdu 3996 最大权闭合图 最后一斩

    hdu 3061 Battle :一看就是明显的最大权闭合图了,水提......SB题也不说边数多少....因为开始时候数组开小了,WA....后来一气之下,开到100W,A了.. hdu3996. ...

  4. hdu 3879 Base Station 最大权闭合图

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3879 A famous mobile communication company is plannin ...

  5. BZOJ 1497 最大获利(最大权闭合图)

    1497: [NOI2006]最大获利 Time Limit: 5 Sec  Memory Limit: 64 MB Submit: 4686  Solved: 2295 [Submit][Statu ...

  6. 最大权闭合图 && 【BZOJ】1497: [NOI2006]最大获利

    http://www.lydsy.com/JudgeOnline/problem.php?id=1497 最大权闭合图详细请看胡伯涛论文<最小割模型在信息学竞赛中的应用>,我在这里截图它的 ...

  7. BZOJ 1497 JZYZOJ 1344 [NOI2006]最大获利 网络流 最大权闭合图

    http://www.lydsy.com/JudgeOnline/problem.php?id=1497 http://172.20.6.3/Problem_Show.asp?id=1344   思路 ...

  8. hdu 3879 hdu 3917 构造最大权闭合图 俩经典题

    hdu3879  base station : 各一个无向图,点的权是负的,边的权是正的.自己建一个子图,使得获利最大. 一看,就感觉按最大密度子图的构想:选了边那么连接的俩端点必需选,于是就以边做点 ...

  9. 最大获利 HYSBZ - 1497 (最大权闭合图)

    最大权闭合图: 有向图,每个点有点权,点权可正可负.对于任意一条有向边i和j,选择了点i就必须选择点j,你需要选择一些点使得得到权值最大. 解决方法: 网络流 对于任意点i,如果i权值为正,s向i连容 ...

随机推荐

  1. 解决Ubuntu14.04在外接显示器不能指定问题的最佳分辨率

    通常这种情况发生.在System Settings -> display 你会发现多出了一个 unknown display. 这往往是因为你使用质量低劣的视频电缆,例如,几美元VGA线. 解决 ...

  2. WPF ContextMenu 在MVVM模式中绑定 Command及使用CommandParameter传参

    原文:WPF ContextMenu 在MVVM模式中绑定 Command及使用CommandParameter传参 ContextMenu无论定义在.cs或.xaml文件中,都不继承父级的DataC ...

  3. UNITY VR 视频/图片 开发心得(二)

    上回说到了普通的全景图片,这回讲真正的VR. 由于这种图片分为两部分,所以我们需要两个Camera对象以及两个球体.首先新建一个Camera对象,并将其命名为RightEye(其它名字也无妨,只要你自 ...

  4. 零元学Expression Blend 4 - Chapter 5 2.5D转换的使用技巧

    原文:零元学Expression Blend 4 - Chapter 5 2.5D转换的使用技巧 本章将延续上篇零元学Expression Blend4 - Chapter 4元件重复运用的观念所制作 ...

  5. C#通过HttpListener实现HTTP监听

    代码: using NLog; using System; using System.Diagnostics; using System.IO; using System.Net; using Sys ...

  6. WPF生成二维码

    WPF可以通过ZXing.Net库来实现二维码的功能. 可以通过NuGet安装: Install-Package ZXing.Net 二维码的实现代码: #region 二维码的方法 /// < ...

  7. 【JDK源码分析】String的存储区与不可变 专题

    <Think in Java>中说:“关系操作符生成的是一个boolean结果,它们计算的是操作数的值之间的关系”. "=="判断的是两个对象的内存地址是否一样,适用于 ...

  8. Use Spring @Scheduled To Achieve Timing Task

    Today I have a chance to use the @Scheduled to achieve a timing task.It is useful.Anyway,it was the ...

  9. UWP开发-在UWP中使用sqlite

    原文:UWP开发-在UWP中使用sqlite sqlite是一种轻量级的数据库,对于一些资源紧张又需要数据库的开发非常好用. SQLite 是一个开源的无服务器嵌入式数据库. 这些年来,它已作为面向存 ...

  10. C#函数参数前的修饰符

    函数的形参前可以带三种修饰符,分别的out.ref.param. out:让函数可以输出“多个值”,并不是真正的输出多个值. ref:相当于引用传递,在函数内部赋值会影响变量的值. params:可变 ...