http://poj.org/problem?id=3680

题意:给出n个区间[Li,Ri],每个区间有一个权值wi,要使得每个点都不被超过k个区间覆盖(最多能被k个区间覆盖),如果选取了第i个区间,那么能得到wi的权值,问最终能得到的最大权值是多少。

思路:首先把区间离散化,然后考虑构图。

第一种构图方式:

将S到第一个区间结点连一条容量为k,费用为0的边,代表最多能使用k个区间。

对于每个区间[l,r],从l到r连一条容量为1,费用为-w[i]的边(因为跑的是最大的费用),这里如果这条边的流量为1,那么代表使用了这个区间,那么就加上费用。

将最后一个区间结点连一条容量为k,费用为0的边,同S。

对于每个离散化后的区间,将i和i+1连一条容量为INF,费用为0的边,如果不跑这条边,那么说明这段区间被覆盖了。

最后将答案取反就是最终答案。

画了个图帮助理解:如果跑1->3的区间的话,那么1->3的流量是1,那么主路径在[1,3]的时候流量为k-1,然后跑2->4,主路径在[2,3]的流量就变成k-2,跑到3的时候就变回k-1,跑到4又变回k,如果k=0的时候,那么就不能被覆盖了,因此恰好可以满足限制。

第二种构图方式:

是挑战上的,对于有负权边的构图。

S和T和i到i+1的连边和上图一样。

对于[u,v],S到v连一条容量为1,费用为0的边,u到T连一条容量为1,费用为0的边,v到u连一条容量为1,费用为wi的边。

这个方法还不太理解。

  1. #include <cstdio>
  2. #include <algorithm>
  3. #include <iostream>
  4. #include <cstring>
  5. #include <string>
  6. #include <cmath>
  7. #include <queue>
  8. #include <vector>
  9. #include <map>
  10. #include <set>
  11. #include <stack>
  12. using namespace std;
  13. #define INF 0x3f3f3f3f
  14. #define N 510
  15. typedef long long LL;
  16. struct Edge {
  17. int u, v, nxt, cap, cost;
  18. } edge[N*N];
  19. int head[N], tot, pre[N], dis[N], vis[N], a[N], b[N], w[N], S, T;
  20. vector<int> vec;
  21.  
  22. void Add(int u, int v, int cap, int cost) {
  23. edge[tot] = (Edge) { u, v, head[u], cap, cost }; head[u] = tot++;
  24. edge[tot] = (Edge) { v, u, head[v], , -cost }; head[v] = tot++;
  25. }
  26.  
  27. bool SPFA(int S) {
  28. queue<int> que;
  29. que.push(S);
  30. memset(dis, INF, sizeof(dis));
  31. memset(vis, , sizeof(vis));
  32. dis[S] = ; vis[S] = ;
  33. while(!que.empty()) {
  34. int u = que.front(); que.pop();
  35. vis[u] = ;
  36. for(int i = head[u]; ~i; i = edge[i].nxt) {
  37. int v = edge[i].v, cost = edge[i].cost, cap = edge[i].cap;
  38. if(dis[v] > dis[u] + cost && cap > ) {
  39. dis[v] = dis[u] + cost;
  40. pre[v] = i;
  41. if(!vis[v]) vis[v] = , que.push(v);
  42. }
  43. }
  44. }
  45. return dis[T] < INF;
  46. }
  47.  
  48. int MFMC(int S, int T) {
  49. int ans = , u, flow;
  50. while(SPFA(S)) {
  51. flow = INF, u = T;
  52. while(u != S) {
  53. if(flow > edge[pre[u]].cap) flow = edge[pre[u]].cap;
  54. u = edge[pre[u]].u;
  55. } u = T;
  56. while(u != S) {
  57. edge[pre[u]].cap -= flow; edge[pre[u]^].cap += flow;
  58. ans += flow * edge[pre[u]].cost;
  59. u = edge[pre[u]].u;
  60. }
  61. }
  62. return ans;
  63. }
  64.  
  65. int main() {
  66. int n, k, t; scanf("%d", &t);
  67. while(t--) {
  68. scanf("%d%d", &n, &k);
  69. memset(head, -, sizeof(head)); tot = ;
  70. vec.clear();
  71. for(int i = ; i <= n; i++)
  72. scanf("%d%d%d", &a[i], &b[i], &w[i]), vec.push_back(a[i]), vec.push_back(b[i]);
  73. sort(vec.begin(), vec.end());
  74. vec.erase(unique(vec.begin(), vec.end()), vec.end()); // 新的离散化姿势
  75. int cnt = vec.size();
  76. S = , T = cnt + ;
  77. int ans = ;
  78.  
  79. // First
  80. Add(S, , k, ); Add(cnt, T, k, );
  81. for(int i = ; i < cnt; i++) Add(i, i + , INF, );
  82. for(int i = ; i <= n; i++) {
  83. int u = lower_bound(vec.begin(), vec.end(), a[i]) - vec.begin() + ;
  84. int v = lower_bound(vec.begin(), vec.end(), b[i]) - vec.begin() + ;
  85. Add(u, v, , -w[i]);
  86. }
  87. ans -= MFMC(S, T);
  88.  
  89. // Second
  90. // Add(S, 1, k, 0); Add(cnt, T, k, 0);
  91. // for(int i = 1; i < cnt; i++) Add(i, i + 1, INF, 0);
  92. // for(int i = 1; i <= n; i++) {
  93. // int u = lower_bound(vec.begin(), vec.end(), a[i]) - vec.begin() + 1;
  94. // int v = lower_bound(vec.begin(), vec.end(), b[i]) - vec.begin() + 1;
  95. // Add(S, v, 1, 0); Add(u, T, 1, 0);
  96. // Add(v, u, 1, w[i]);
  97. // ans += w[i];
  98. // }
  99. // ans -= MFMC(S, T);
  100. printf("%d\n", ans);
  101. }
  102. return ;
  103. }
  104.  
  105. /*
  106. 3 1
  107. 1 2 2
  108. 2 3 4
  109. 3 4 8
  110. 3 1
  111. 1 3 2
  112. 2 3 4
  113. 3 4 8
  114. 3 2
  115. 1 100000 100000
  116. 1 150 301
  117. 100 200 300
  118. */

POJ 3680:Intervals(最小费用最大流)***的更多相关文章

  1. POJ 3680 Intervals 最小费用最大流(MCMF算法)

    题意:给出 n ,k 表示接下来给你 n 段开区间,每段区间都有它的权值,问选出一些区间,使它的权值最大,并且在实轴上的每个点,不得超过 k次被覆盖. 思路:首先要理解建图思路,首先有一个基图,相邻点 ...

  2. POJ 3680 Intervals(费用流)

    Intervals Time Limit: 5000MS   Memory Limit: 65536K Total Submissions: 5762   Accepted: 2288 Descrip ...

  3. POJ 3680 Intervals(费用流+负权优化)

    [题目链接] http://poj.org/problem?id=3680 [题目大意] 有N个带权重的区间,现在要从中选取一些区间, 要求任意点都不被超过K个区间所覆盖,请最大化总的区间权重. [题 ...

  4. Going Home POJ - 2195 (最小费用最大流)

    On a grid map there are n little men and n houses. In each unit time, every little man can move one ...

  5. poj 3680 Intervals(费用流)

    http://poj.org/problem?id=3680 巧妙的构图. 题目:给定N个区间(ai,bi)权值wi,求最大权和且每个点最多覆盖K次. 构图:将区间端点离散化,将第i个点连第i+1个点 ...

  6. poj3680 Intervals 区间k覆盖问题 最小费用最大流 建图巧妙

    /** 题目:poj3680 Intervals 区间k覆盖问题 最小费用最大流 建图巧妙 链接:http://poj.org/problem?id=3680 题意:给定n个区间,每个区间(ai,bi ...

  7. POJ 2195:Going Home(最小费用最大流)

    http://poj.org/problem?id=2195 题意:有一个地图里面有N个人和N个家,每走一格的花费是1,问让这N个人分别到这N个家的最小花费是多少. 思路:通过这个题目学了最小费用最大 ...

  8. poj 2195 二分图带权匹配+最小费用最大流

    题意:有一个矩阵,某些格有人,某些格有房子,每个人可以上下左右移动,问给每个人进一个房子,所有人需要走的距离之和最小是多少. 貌似以前见过很多这样类似的题,都不会,现在知道是用KM算法做了 KM算法目 ...

  9. POJ 2157 Evacuation Plan [最小费用最大流][消圈算法]

    ---恢复内容开始--- 题意略. 这题在poj直接求最小费用会超时,但是题意也没说要求最优解. 根据线圈定理,如果一个跑完最费用流的残余网络中存在负权环,那么顺着这个负权环跑流量为1那么会得到更小的 ...

  10. POJ 2195 Going Home(最小费用最大流)

    http://poj.org/problem?id=2195 题意 :  N*M的点阵中,有N个人,N个房子.让x个人走到这x个房子中,只能上下左右走,每个人每走一步就花1美元,问当所有的人都归位了之 ...

随机推荐

  1. Coder-Strike 2014 - Finals (online edition, Div. 1)

    CF 420A  A. Start Up 题目链接: http://codeforces.com/problemset/problem/420/A 题目意思: 给一个字符串A,通过镜面反射后得到A', ...

  2. 将RDL报表转换成RDLC报表的函数

    原文:将RDL报表转换成RDLC报表的函数 近日研究RDLC报表,发现其不能与RDL报表兼容,尤其是将RDL报表转换成RDLC报表.网上的资料贴出的的转换方式复杂且不切实际,遂决定深入研究.经研究发现 ...

  3. css3的calc() css3的百分比减宽,减高,加,乘,除,适合用于后台的排版定位

    css3的calc() css3的百分比减宽,减高,加,乘,除,适合用于后台的排版定位 浏览器支持IE9+.FF4.0+.Chrome19+.Safari6+ calc()语法非常简单,就像我们小时候 ...

  4. C#基础加强篇----委托、Lamada表达式和事件(上)

    1.委托 C#的委托相当于C/C++中的函数指针.函数指针用指针获取一个函数的入口地址,实现对函数的操作. 委托与C/C++中的函数指针不同在于,委托是面向对象的,是引用类型,对委托的使用要先定义后实 ...

  5. 【转载】动态载入DLL所需要的三个函数详解(LoadLibrary,GetProcAddress,FreeLibrary)

    原文地址:https://www.cnblogs.com/westsoft/p/5936092.html 动态载入 DLL 动态载入方式是指在编译之前并不知道将会调用哪些 DLL 函数, 完全是在运行 ...

  6. intel汇编笔记

    另一篇汇编学习笔记AT&T Assembly on Linux  (linux下) mov ax,bx     bx到ax 读数据过程:cpu通过地址线发送地址a,控制线向存储器发送读命令,存 ...

  7. 【Windows10 IoT开发系列】开发人员模式设置

    原文:[Windows10 IoT开发系列]开发人员模式设置  声明:本文转自微软Windows 开发人员中心(https://msdn.microsoft.com/library/windows/ ...

  8. Android Studio 添加 Genymotion插件

    原文:Android Studio 添加 Genymotion插件 1.下载Genymotion:官网地址,必须先注册才能下载,下载带有VirtualBox的版本 2.安装:安装时会连VirtualB ...

  9. 常见的几个Qt编程问题的处理(转自QT中文论坛)(挺实用的)

    1.如何在窗体关闭前自行判断是否可关闭答:重新实现这个窗体的closeEvent()函数,加入判断操作 void MainWindow::closeEvent(QCloseEvent*event){i ...

  10. C++的 RTTI 观念和用途(非常详细)

    自从1993年Bjarne Stroustrup [注1 ]提出有关C++ 的RTTI功能之建议﹐以及C++的异常处理(exception handling)需要RTTI:最近新推出的C++ 或多或少 ...