POJ 3680 Intervals
来源:互联网 发布:淘宝买射钉枪警察找我 编辑:程序博客网 时间:2024/06/06 01:55
题目在这里呀
哎失望地开始口糊题解了呀,bzoj2879 TLE调不出来,于是难过地开始整理AC的题了(ಥ﹏ಥ)...
这题很有想法的!
题意:有n个区间,每个区间有一个权值wi,从中取一些区间,使得任意整数点的被包含次数小于等于k,并且这些区间的权值和最大。
题解:这题和志愿者招募蜜汁相似啊ww~~
对于每个点列出式子。
设xi表示第i个区间有没有包含该点,xi=0 or 1
再引入一个余量ri
这样式子可以写成:
0+r0=k
x1+x3+x6+r1=k
x2+x5+x6+r2=k
......
0+rn+1=k
相邻两点相减,x2+x5+r2-x1-x3-r1=0
看见右端为0,可以想到一个点的入流=出流。
而相邻两个点相减多出来的一定是新产生的或者是新消失的。
那么就可以把问题转化成费用流啦!
区间的两个端点连边,流量为1,费用为-wi(否则不会去流)
相邻端点之间连边,流量为k,费用为0
建立源点和汇点与第一个和最后一个点连边。
跑费用流即可。
这题或许有点难理解(真的w
边数初始化1这个东西永远不能忘!!
#include <iostream>#include <cstdio>#include <cstring>#include <algorithm>#include <cmath>#include <queue>#include <map>#define N 1010using namespace std;int Q,n,k,cnt,tot,S,T,ans,mark[N],dis[N],head[N],cur[N],c[N],a[N],b[N],w[N];map<int,int> id;const int inf=1e9;struct edge{int from,to,next,v,c;}e[N];inline int read(){ int x=0,f=1;char ch=getchar(); while (ch<'0' || ch>'9'){if (ch=='-') f=-1;ch=getchar();} while (ch>='0' && ch<='9'){x=x*10+ch-'0';ch=getchar();} return x*f;}inline void add_edge(int x,int y,int v,int c){e[++cnt]=(edge){x,y,head[x],v,c};head[x]=cnt;e[++cnt]=(edge){y,x,head[y],0,-c};head[y]=cnt;}inline bool spfa(){memset(mark,0,sizeof(mark));for(int i=0;i<=T;i++) dis[i]=inf;queue<int>q;dis[S]=0;q.push(S);mark[S]=1;while(!q.empty()){int now=q.front();q.pop();for(int i=head[now];i!=-1;i=e[i].next){int v1=e[i].to;if(e[i].v && dis[v1]>dis[now]+e[i].c){dis[v1]=dis[now]+e[i].c;cur[v1]=i;if(!mark[v1]){q.push(v1);mark[v1]=1;}}}mark[now]=0;}return dis[T]!=inf;}inline void mcf(){ans=0;while(spfa()){int flow=inf;for(int i=cur[T];i;i=cur[e[i].from]) flow=min(flow,e[i].v);ans+=flow*dis[T];for(int i=cur[T];i;i=cur[e[i].from]){e[i].v-=flow;e[i ^ 1].v+=flow;}}}int main(){Q=read();while(Q--){memset(head,-1,sizeof(head));memset(cur,0,sizeof(cur));memset(c,0,sizeof(c));n=read();k=read();for(int i=1;i<=n;i++){a[i]=read();b[i]=read();w[i]=read();c[i+i-1]=a[i];c[i+i]=b[i];}sort(c+1,c+n+n+1);tot=0;cnt=1;for(int i=1;i<=n+n;i++) if(i==1 || c[i] != c[i-1]) id[c[i]]=++tot;S=0;T=tot+1;for(int i=1;i<tot;i++) add_edge(i,i+1,k,0);add_edge(S,1,k,0);add_edge(tot,T,k,0);for(int i=1;i<=n;i++) add_edge(id[a[i]],id[b[i]],1,-w[i]);mcf();printf("%d\n",-ans);}return 0;}
阅读全文
0 0
- POJ 3680 Intervals
- poj 3680 intervals
- POJ-3680-Intervals
- poj 3680 Intervals
- POJ 3680 Intervals
- POJ 3680 Intervals
- poj 3680 intervals
- POJ 3680 Intervals
- POJ 3680 Intervals 笔记
- POJ 3680 Intervals
- poj 3680 Intervals 费用流
- poj 3680 Intervals 费用流
- 【网络流】 POJ 3680 Intervals
- poj 3680 Intervals(费用流)
- [费用流] POJ 3680 Intervals
- poj 3680 Intervals 经典的建图!
- 【POJ】 3680 Intervals 离散 + 费用流
- POJ 3680 Intervals(最小费用流)
- 合并二叉排序树
- Linux C编程 第13章进程间通信方式十个问题及解答(2)
- 数据结构与算法--栈与队列
- Concave and Convex Function
- 匿名内部类使用的外部变量为什么要是final的
- POJ 3680 Intervals
- VirtualQueryEx详解
- Matlab—寻找峰值函数介绍
- opencv cuda
- kafka分布式消息队列 — 基本概念介绍
- PHP 引用在线编辑器,kindeditor
- apt() 问题
- 习题8
- 深度学习中的「卷积层」如何深入理解?