题意:

给定区间和该区间对应的权值,挑选一些区间,求使得每个数都不被K个区间覆盖的最大权值和。

分析:

如果K=1,即为区间图的最大权独立集问题。可以对区间所有端点排序后利用动态规划的方法,设dp[i]为只考虑区间右端点小于等于xi的区间所得到的最大总权重。

dp[i] = max(dp[i - 1], max{dp[j] + w[k])|a[k] = x[j]且b[k] = x[i]}

K>1,既然求权重最大值,利用最小费用流,很容易想到从a[i]到b[i]连一条容量为1,费用为−w[i]的边,但是如何限制每个数不被超过K个区间覆盖呢?从i到i+1连一条容量为K,费用为0的边,这样便限制了流经每个端点的流量不超过K,也就满足每个数不被超过K个区间覆盖啦~注意区间端点的离散化~~

代码:

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<queue>
using namespace std;
const int maxn = 505, maxm = 1000;
const int INF = 0x3f3f3f3f;
int s, t, tot;
int dist[maxm], prevv[maxm], preve[maxm], head[maxm];
int a[maxn], b[maxn], w[maxn], tt[maxm];
bool in[maxn];
struct Edge{ int from, to, next, cap, cost;}edge[maxm * 3];
void add_edge(int from, int to, int cap, int cost)
{
edge[tot].to = to;
edge[tot].from = from;
edge[tot].cap = cap;
edge[tot].cost = cost;
edge[tot].next = head[from];
head[from] = tot++;
edge[tot].to = from;
edge[tot].from = to;
edge[tot].cap = 0;
edge[tot].cost = -cost;
edge[tot].next = head[to];
head[to] = tot++;
}
int mincost()
{
int flow=0, cost=0;
for(;;){
memset(dist, 0x3f, sizeof(dist));
memset(in, false, sizeof(in));
queue<int>q;
q.push(s);
in[s] = true;
dist[s]=0;
while(!q.empty()){
int u = q.front();q.pop();
in[u] = false;
for(int i = head[u]; i != -1; i = edge[i].next){
Edge e = edge[i];
if(e.cap>0 && dist[e.to] > dist[u] + e.cost){
dist[e.to] = dist[u] + e.cost;
prevv[e.to] = u, preve[e.to] = i;
if(!in[e.to]){
in[e.to] = true;
q.push(e.to);
}
}
}
}
if(dist[t] == INF) return cost;
int d = INF;
for(int i = t; i != s; i = prevv[i])
d = min(d, edge[preve[i]].cap);
flow += d;
cost += dist[t] * d;
for(int i = t; i != s; i = prevv[i]){
edge[preve[i]].cap -= d;
edge[preve[i]^1].cap += d;
}
}
}
int main()
{
int c;scanf("%d",&c);
while(c--){
int N, K;
memset(head,-1,sizeof(head));
tot = 0;
int n = 0;
scanf("%d%d",&N, &K);
for(int i = 0; i < N; i++){
scanf("%d%d%d", &a[i], &b[i], &w[i]);
tt[n++] = a[i];
tt[n++] = b[i];
}
sort(tt, tt + n);
int nn = unique(tt, tt +n) - tt;
int na, nb;
for(int i = 0; i < N; i++){
na = lower_bound(tt, tt + nn, a[i]) - tt;
nb = lower_bound(tt, tt + nn, b[i]) - tt;
add_edge(na + 1, nb + 1, 1, -w[i]);
}
s = 0, t = nn + 1;
add_edge(s, 1, K, 0);
for(int i = 1; i <= nn; i++)
add_edge(i, i + 1, K, 0);
printf("%d\n",-mincost());
}
return 0;
}

其实这题也可以是从i+1向i连一条容量为1,权值为w[i]的边,用求出的最小费用流减去所有区间权值和,再取负数就好啦~实际上是取最小费用流对应的区间之外的区间,因为建图保证每个点都不被超过K个区间覆盖,所以不用担心与题目不符啦~~


tle了一整天。。。。

很巧妙的构图~~~

POJ 3680_Intervals的更多相关文章

  1. POJ 3370. Halloween treats 抽屉原理 / 鸽巢原理

    Halloween treats Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 7644   Accepted: 2798 ...

  2. POJ 2356. Find a multiple 抽屉原理 / 鸽巢原理

    Find a multiple Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 7192   Accepted: 3138   ...

  3. POJ 2965. The Pilots Brothers' refrigerator 枚举or爆搜or分治

    The Pilots Brothers' refrigerator Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 22286 ...

  4. POJ 1753. Flip Game 枚举or爆搜+位压缩,或者高斯消元法

    Flip Game Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 37427   Accepted: 16288 Descr ...

  5. POJ 3254. Corn Fields 状态压缩DP (入门级)

    Corn Fields Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 9806   Accepted: 5185 Descr ...

  6. POJ 2739. Sum of Consecutive Prime Numbers

    Sum of Consecutive Prime Numbers Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 20050 ...

  7. POJ 2255. Tree Recovery

    Tree Recovery Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 11939   Accepted: 7493 De ...

  8. POJ 2752 Seek the Name, Seek the Fame [kmp]

    Seek the Name, Seek the Fame Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 17898   Ac ...

  9. poj 2352 Stars 数星星 详解

    题目: poj 2352 Stars 数星星 题意:已知n个星星的坐标.每个星星都有一个等级,数值等于坐标系内纵坐标和横坐标皆不大于它的星星的个数.星星的坐标按照纵坐标从小到大的顺序给出,纵坐标相同时 ...

随机推荐

  1. 客户端负载均衡 - Ribbon

    Ribbon是Netflix公司开源的一个负载均衡的项目(https://github.com/Netflix/ribbon),它是一个基于HTTP.TCP的客户端负载均衡器. 服务端负载均衡 负载均 ...

  2. Vue 学习之el、template、replace和vue的生命周期 参考网址:https://segmentfault.com/a/1190000008010666

  3. CCF|游戏|Java

    import java.util.Scanner; public class tyt { public static void main(String[] args) { Scanner in = n ...

  4. Android学习笔记(七) 布局基础

    一.概念 控件布局方法,就是指控制控件在Activity当中的位置.大小.颜色以及其他控件样式属性的方法.有两种方法可以控制布局: 在布局文件(xxx.xml)中完成控件的布局. 在JAVA代码中完成 ...

  5. oracle DBA笔试题

    Unix/Linux题目: 1.如何查看主机CPU.内存.IP和磁盘空间? cat /proc/cpuinfo cat /proc/meminfo ifconfig –a fdisk –l   2.你 ...

  6. js获取select选中的标签option的值

      js中获取方法 var obj = document.getElementByIdx_xx_x(”testSelect”); //定位id var index = obj.selectedInde ...

  7. Android(java)学习笔记196:ContentProvider使用之内容观察者01

    1. 内容观察者 不属于四大组件,只是内容提供者ContentProvider对应的小功能. 如果发现数据库内容变化了,就会立刻观察到. 下面是逻辑图:       当A应用中银行内部的数据发生变化的 ...

  8. Maven常用仓库地址以及手动添加jar包到仓库

    http://www.blogjava.net/fancydeepin 共有的仓库 http://repository.sonatype.org/content/groups/public/http: ...

  9. 08JavaScript数学与日期时间对象

    JavaScript数学与日期时间对象 5.1.3数学(Math)对象 <script> //欧拉常量,自然对数的底(约等于2.718); document.write(Math.E+&q ...

  10. CSU2179: 找众数

    Description 由文件给出N个1到30000间无序数正整数,其中1≤N≤10000,同一个正整数可能会出现多次,出现次数最多的整数称为众数.求出它的众数及它出现的次数. Input 输入文件第 ...