描述:

http://codevs.cn/problem/1789/


题解:

第一次写最大闭合子图的题,把过程写详细。

如果要选择第i个用户群,那么就必须选择中转站ai和bi。而这个约束条件是最大闭合子图的经典条件,先来看看最大闭合子图的定义:

最大权闭合子图即为,给定一个图,每个点有一个权值,有正有负。有一些有向边(i,j),表示若选了点i,那么也必须选点j。请求出一个合法点集使得点权和尽量大.

然后开始建模:
首先建立二分图,建立附加源s和附加汇t,从s到每个用户群连一条容量为ci的边,表示选择这个用户群的收益;从每个中转站到t连一条容量为pi的边,表示中转站的成本,注意这个成本其实是负数,这里取相反数即正值,后面要转化。再从用户群到需要的中转站连一条容量为INF的边。求s到t的最大流,用户群的权值和-最大流量就是最终结果。

分析:
最大流一定对应一个最小割,那么考虑这样一组边:s->ci->ai、bi->t,其中有且只有一条边在最小割中【1】,且只能为s->ai(bi)和ci->t中的一条【2】,因为最小割的性质得出【1】,而用户群和中转站之间的边容量已经被设为INF,不会满流得出【2】。

假设所有用户群都选择并且不需要任何中转站,此时获利为Total。然后我们让割集的流量代表相对Total损失的钱。损失的钱包括两部分:1.放弃选择的用户群所带来的收益;2.选择一些必要的中转站需要的成本。

  1. 如果s->ci在最小割中,代表损失掉ci的钱,那么就没有选择ci这个中转站。对相应ai和bi没有影响。
  2. 相反的,如果s->ci不在最小割中,则代表选择ci这个中转站(因为不损失ci的获利),那么相应ai、bi->t的边一定在最小割中,代表选择ai和bi(损失这些成本)。这样就满足了选择ci,ai、bi一定被选。

最后要让损失的钱最少,也就是割的流量最小,最小割流量对应着最大流MaxFlow,那么

ans=Total−MaxFlow;

ans = Total - MaxFlow;


代码:

454ms 12MB

#include<cstdio>
#include<cstring>
#include<vector>
#include<queue>
using namespace std;const int maxn = 5000 + 10;
const int maxnode = 50000 + 5000 + 10;
const int INF = 1e9 + 7;struct Edge {int from, to, cap, flow;
};struct ISAP
{int n, m, s, t;vector<Edge> edges;vector<int> G[maxnode]; bool vis[maxnode]; int d[maxnode], cur[maxnode], p[maxnode], num[maxnode]; void AddEdge(int from, int to, int cap) {edges.push_back((Edge){from, to, cap, 0});edges.push_back((Edge){to, from, 0, 0});m = edges.size();G[from].push_back(m-2);G[to].push_back(m-1);}bool BFS() {memset(vis, 0, sizeof(vis));queue<int> Q;Q.push(t);vis[t] = 1;d[t] = 0;while(!Q.empty()) {int x = Q.front(); Q.pop();for(int i = 0; i < G[x].size(); i++) {Edge& e = edges[G[x][i]^1];if(!vis[e.from] && e.cap > e.flow) {vis[e.from] = 1;d[e.from] = d[x] + 1;Q.push(e.from);}}}return vis[s];}int Augment() {int x = t, a = INF;while(x != s) {Edge& e = edges[p[x]];a = min(a, e.cap-e.flow);x = edges[p[x]].from;}x = t;while(x != s) {edges[p[x]].flow += a;edges[p[x]^1].flow -= a;x = edges[p[x]].from;}return a;}int Maxflow(int s, int t, int n) {this->s = s; this->t = t; this->n = n;int flow = 0;BFS();memset(num, 0, sizeof(num));for(int i = 0; i < n; i++) num[d[i]]++;int x = s;memset(cur, 0, sizeof(cur));while(d[s] < n) {if(x == t) {flow += Augment();x = s;}int ok = 0;for(int i = cur[x]; i < G[x].size(); i++) {Edge& e = edges[G[x][i]];if(e.cap > e.flow && d[x] == d[e.to] + 1) { ok = 1;p[e.to] = G[x][i];cur[x] = i;x = e.to;break;}}if(!ok) { int m = n-1;for(int i = 0; i < G[x].size(); i++) {Edge& e = edges[G[x][i]];if(e.cap > e.flow) m = min(m, d[e.to]);}if(--num[d[x]] == 0) break;num[d[x] = m+1]++;cur[x] = 0; if(x != s) x = edges[p[x]].from;}}return flow;}
}isap;int p[maxn];int main()
{int n, m, s, t;scanf("%d%d", &n, &m);s = 0; t = m + n + 1;for(int i = m + 1; i <= m + n; i++) {int p;scanf("%d", &p);isap.AddEdge(i, t, p);}int tot = 0;for(int i = 1; i <= m; i++) {int a, b, c;scanf("%d%d%d", &a, &b, &c);tot += c; isap.AddEdge(s, i, c);isap.AddEdge(i, a + m, INF);isap.AddEdge(i, b + m, INF);}printf("%d\n", tot - isap.Maxflow(s, t, t+1));return 0;
}

[codevs 1789] 最大获利(2006年NOI全国竞赛)相关推荐

  1. 【CodeVS 1540】银河英雄传说 2002年NOI全国竞赛

    noi这么水? 很久没有自己不看题解A题了 ~~~~~~ 带权并查集! CodeVS的数据不合规定??有乱七八糟的字符?? 见我注释掉的读入![刚又测试 洛谷用被注释掉的那一句也可以A 说明CadeV ...

  2. 河南2002年计算机比赛,2004-2005学年我校国际、全国竞赛获奖情况统计

    一.第36届中学生国际化学奥林匹克竞赛 2004年7月在德国基尔举行的第36届中学生国际化学奥林匹克竞赛中,我校学生岳衎代表我国参赛并获得金牌.全国参加此赛事的选手共4人. 二.第二十一届全国中学生物 ...

  3. 合肥市noi计算机竞赛,合肥第一,获“强基计划”资格!孙乐然斩获第37届全国信息学奥林匹克竞赛银牌...

    在2020第37届全国青少年信息学奥林匹克竞赛中,合肥八中孙乐然同学以371分的高分摘得银牌,取得八中信息学历史最佳成绩. 8月的长沙骄阳似火,比烈日更加火热的是来自全国27个省市自治区300余名智慧 ...

  4. Codevs 1010 过河卒 2002年NOIP全国联赛普及组

    1010 过河卒 2002年NOIP全国联赛普及组 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 黄金 Gold 传送门 题目描述 Description 如图,A 点有一个过河卒 ...

  5. 全国竞赛算不算全国计算机二级,竞赛证书的等级如何区分

    原标题:竞赛证书的等级如何区分 在五项学科竞赛中,不少人以为拿了省级赛区(联赛.复赛.国初)的奖项就是全国决赛奖项了.其实五项学科竞赛各级奖项有区别.今天为大家整理了<五项学科竞赛证书等级指南( ...

  6. 合肥市noi计算机竞赛,2012年蜀山区青少年信息学(计算机)竞赛通知

    合肥奥数网讯:关于举办2012年蜀山区青少年信息学(计算机)竞赛的通知如下 蜀山区各小学: 为进一步推动中小学计算机教育的开展,促进我区学生信息学(计算机)知识的普及与提高,同时为合肥市青少年信息学( ...

  7. 湖北省专科计算机竞赛,NOI信息学竞赛2019年湖北省队名单

    CCF NOI2019湖北省省队选拔活动于2019年4月6-7日在湖北武汉华中科技大学举行,由湖北省计算机学会组织.本次选拔活动分为两试,均为机试.最终成绩按照NOIP2018提高组成绩和省队选拔成绩 ...

  8. 一次全国竞赛笔试时的试题

    1. 在下面给出的SQL语句中,哪一行代码会导致语句失败() 1  select lastname,firstname,email 2  from customer,emailusers 3  on ...

  9. AC日记——食物链 codevs 1047

    1074 食物链 2001年NOI全国竞赛  时间限制: 3 s  空间限制: 64000 KB  题目等级 : 钻石 Diamond 题解 题目描述 Description 动物王国中有三类动物 A ...

最新文章

  1. 伟大前程与技术难关:量子机器学习该如何走进现实?
  2. python网络爬虫的基本步骤-Python网络爬虫学习手记(1)——爬虫基础
  3. phpstudy安装ssl证书_新版Siteground一键安装免费SSL证书 网站https安全访问
  4. apache站点优化——长连接
  5. php中生成标准uuid(guid)的方法
  6. ​【v2.x OGE-example 第二节】 实体参数
  7. python程序执行时间_用于在Python中查找程序执行时间的程序
  8. php 日期format不要零_PHP格式化日期用法代码,包括前导零示例
  9. Jquery Ajax 请求示例
  10. 清华学霸组团的工业 AIoT 创企再获数千万融资:玩家应推动在边缘 AI 芯片上跑算法...
  11. $PollardRho$ 算法及其优化详解
  12. Word限制编辑忘记密码怎么解锁
  13. 番外2. OpenCV 中摄像头捕获与视频处理与常见问题解决方案
  14. 子平真诠释疑笔记(四)
  15. 消息系统(ActiveMQ)
  16. pygame 游戏开发
  17. android epub 开源,EPUB SDK
  18. 自媒体怎么赚钱!自媒体怎么做收益比较高!
  19. ViewPager.setOffscreenPageLimit
  20. echarts 鼠标经过时改变折线拐点的小圆圈样式

热门文章

  1. 算法导论-排序算法-分治法
  2. *.bmp序列保存为*.raw文件[matlb实现]
  3. 最简单的c#Remoting编程
  4. C语言中巧妙的使用#和##
  5. 查看提交历史 —— Git 学习笔记 11
  6. 程序员面试系列——冒泡排序
  7. 【放洋屁了】知识焦虑-几点感慨
  8. IDEA下maven项目Plugins和Dependencies红线
  9. STM32开发 -- 开发环境搭建
  10. S5PV210开发 -- Linux dd命令