hdu 3879 Base Station bzoj 1497 最大获利问题 最大权闭合子图
2016-02-29 11:33
253 查看
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3879
http://www.lydsy.com/JudgeOnline/problem.php?id=1497
题意:
在前期市场调查和站址勘测之后,公司得到了一共N个可以作为通讯信号中转站的地址,而由于这些地址的地理位置差异,在不同的地方建造通讯中转站需要投入的成本也是不一样的,所幸在前期调查之后这些都是已知数据:建立第i个通讯中转站需要的成本为Pi(1≤i≤N)。另外公司调查得出了所有期望中的用户群,一共M个。关于第i个用户群的信息概括为Ai, Bi和Ci:这些用户会使用中转站Ai和中转站Bi进行通讯,公司可以获益Ci。(1≤i≤M, 1≤Ai, Bi≤N) THU集团的CS&T公司可以有选择的建立一些中转站(投入成本),为一些用户提供服务并获得收益(获益之和)。那么如何选择最终建立的中转站才能让公司的净获利最大呢?(净获利 = 获益之和 - 投入成本之和)
思路:
经典的最大权闭合子图问题。
因为用户通过使用中转站Ai和中转站Bi进行通讯,公司可以获益Ci。即满足这个用户群,就可以得到收益c。
但是获得收益C需要一个必要条件:建立中转站a和b,需要花去一定的费用,这就是满足了闭合图的性质。
所以按照最大权闭合子图的方法来建图。
建立超级源点s和超级汇点t。
s向每个收益点连一条边,容量为ci。
每个站点向t连一条边,容量为pi。
每个需要a, b, i中 i分别向a和b连一条边,容量为inf。
然后求最小割。
答案就是正权点总权和 - 最小割。
http://www.lydsy.com/JudgeOnline/problem.php?id=1497
题意:
在前期市场调查和站址勘测之后,公司得到了一共N个可以作为通讯信号中转站的地址,而由于这些地址的地理位置差异,在不同的地方建造通讯中转站需要投入的成本也是不一样的,所幸在前期调查之后这些都是已知数据:建立第i个通讯中转站需要的成本为Pi(1≤i≤N)。另外公司调查得出了所有期望中的用户群,一共M个。关于第i个用户群的信息概括为Ai, Bi和Ci:这些用户会使用中转站Ai和中转站Bi进行通讯,公司可以获益Ci。(1≤i≤M, 1≤Ai, Bi≤N) THU集团的CS&T公司可以有选择的建立一些中转站(投入成本),为一些用户提供服务并获得收益(获益之和)。那么如何选择最终建立的中转站才能让公司的净获利最大呢?(净获利 = 获益之和 - 投入成本之和)
思路:
经典的最大权闭合子图问题。
因为用户通过使用中转站Ai和中转站Bi进行通讯,公司可以获益Ci。即满足这个用户群,就可以得到收益c。
但是获得收益C需要一个必要条件:建立中转站a和b,需要花去一定的费用,这就是满足了闭合图的性质。
所以按照最大权闭合子图的方法来建图。
建立超级源点s和超级汇点t。
s向每个收益点连一条边,容量为ci。
每个站点向t连一条边,容量为pi。
每个需要a, b, i中 i分别向a和b连一条边,容量为inf。
然后求最小割。
答案就是正权点总权和 - 最小割。
//#include <bits/stdc++.h> #include <iostream> #include <cstring> #include <cstdio> #include <vector> #include <queue> using namespace std; struct Edge { int from, to, cap, flow; Edge(int f, int t, int c, int fl) { from = f; to = t; cap = c; flow = fl; } }; #define maxn 55010 #define inf 0x3f3f3f3f vector <Edge> edges; int n, m, s, t; vector <int> G[maxn]; int d[maxn], vis[maxn], cur[maxn]; 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)); d[s] = 0; vis[s] = 1; queue <int> q; q.push(s); while(!q.empty()) { int x = q.front(); q.pop(); for(int i = 0; i < G[x].size(); i++) { Edge &e = edges[G[x][i]]; if(!vis[e.to] && e.cap > e.flow) { vis[e.to] = 1; d[e.to] = d[x] + 1; q.push(e.to); } } } return vis[t]; } int dfs(int x, int a) { if(x == t || a == 0) return a; int flow = 0, f; for(int &i = cur[x]; i < G[x].size(); i++) { Edge &e = edges[G[x][i]]; if(d[e.to] == d[x]+1 && (f = dfs(e.to, min(a, e.cap - e.flow))) > 0) { e.flow += f; edges[G[x][i]^1].flow -= f; flow += f; a -= f; if(a == 0) break; } } return flow; } int maxflow() { int flow = 0; while(bfs()) { memset(cur, 0, sizeof(cur)); flow += dfs(s, inf); } return flow; } int N, M; int p[5050]; int main() { //freopen("in.txt", "r", stdin); //freopen("out.txt", "w", stdout); while(~scanf("%d%d", &N, &M)) { edges.clear(); s = 0; t = N+M+1; n = N+M+2; for(int i = 0; i <= t; i++) G[i].clear(); for(int i = 1; i <= N; i++) { scanf("%d", &p[i]); AddEdge(i+M, t, p[i]); } int sum = 0; for(int i = 1; i <= M; i++) { int a, b, c; scanf("%d%d%d", &a, &b, &c); sum += c; AddEdge(s, i, c); AddEdge(i, a+M, inf); AddEdge(i, b+M, inf); } int flow = maxflow(); printf("%d\n", sum-flow); } return 0; }
相关文章推荐
- 英语总结
- maven之应用总结
- 产品经理反型记 | 解答新人面试中遇到的问题
- muduo库的学习7---TcpServer与TcpClient的基本设计---总论
- Android控件GridView之仿支付宝钱包首页带有分割线的GridView九宫格的完美实现
- redis3.x cluster设计
- Java中的DatagramPacket与DatagramSocket的初步
- 初窥Linux 之 我最常用的20条命令
- 【转】Java ConcurrentModificationException异常原因和解决方法
- 第一个shell编程,输出hello world!
- 无法解析的外部符号
- 函数工厂
- Android全局异常处理(捕获异常,不弹出程序崩溃)
- 使用eclipse和maven创建activiti项目基础配置
- nCV之CXCORE篇 (3)
- 算法基础 2.1插入排序
- unity 背景动态模糊(blur)和截屏方法
- 使用eclipse和maven创建activiti项目基础配置
- C++中ASCII、unicode与Utf8之间的相互转化
- Communicate BW and ECC