BZOJ 4276 [ONTAK2015]Bajtman i Okrągły Robin 费用流 线段树优化建图
2017-06-19 08:11
519 查看
题目大意:n(≤5000)个区间(l,r≤5000),每个区间只能选其中的一个点得到vi的价值,每个点最多选1次,求最大价值
容易想到费用流。
暴力建图n2条边直接爆炸(不一定
区间加边,可以用线段树优化建图。
线段树上的每个结点表示一个区间,每个区间向子区间连边,表示如果能到这个区间的话就也可以到达子区间。
然后每个区间往线段树结点上表示的区间连边就好了。
容易想到费用流。
暴力建图n2条边直接爆炸(不一定
区间加边,可以用线段树优化建图。
线段树上的每个结点表示一个区间,每个区间向子区间连边,表示如果能到这个区间的话就也可以到达子区间。
然后每个区间往线段树结点上表示的区间连边就好了。
#include <cstdio> #include <cstring> #include <algorithm> #include <queue> #define N 30005 #define INF 1000000000 using namespace std; struct Edge { int from,to,nxt,cap,cost; Edge() {} Edge(int _from,int _to,int _nxt,int _cap,int _cost): from(_from),to(_to),nxt(_nxt),cap(_cap),cost(_cost) {} }e[N*10]; int n,tot=-1,S,T,tot_cost,tot_flow,fir ,d ; bool vis ,inq ; void Add_Edge(int from,int to,int cap,int cost) { e[++tot]=Edge(from,to,fir[from],cap,cost), fir[from]=tot; e[++tot]=Edge(to,from,fir[to],0,-cost), fir[to]=tot; return ; } bool SPFA() { queue<int> q; for(int i=S;i<=T;++i) d[i]=INF; d[S]=0, q.push(S), inq[S]=true; while(!q.empty()) { int x=q.front(); q.pop(); inq[x]=false; for(int i=fir[x];~i;i=e[i].nxt) { if(!e[i].cap || d[e[i].to]<=d[x]+e[i].cost) continue; d[e[i].to]=d[x]+e[i].cost; if(!inq[e[i].to]) q.push(e[i].to), inq[e[i].to]=true; } } return d[T]!=INF; } int dfs(int x,int now) { if(x==T || !now) { tot_cost+=now*d[T]; return now; } vis[x]=true; int f,flow=0; for(int i=fir[x];~i;i=e[i].nxt) { if(vis[e[i].to] || d[e[i].to]!=d[x]+e[i].cost) continue; f=dfs(e[i].to,min(now,e[i].cap)); if(!f) continue; e[i].cap-=f, e[i^1].cap+=f; now-=f, flow+=f; if(!now) break; } if(!flow) d[x]=INF; return flow; } void Costflow() { tot_cost=tot_flow=0; while(SPFA()) { for(int i=S;i<=T;++i) vis[i]=false; tot_flow+=dfs(S,INF); } return ; } struct Node { Node* ch[2]; int num,l,r; Node() {} Node(int _l,int _r,int _num):l(_l),r(_r),num(_num) { ch[0]=ch[1]=NULL; } void* operator new(size_t) { static Node *C,*mempool; if(mempool==C) mempool=(C=new Node[1<<20])+(1<<20); return C++; } }*root; void init(Node*& o,int l,int r,int num) { o=new Node(l,r,num); if(l==r) { Add_Edge(n+num,T,1,0); return ; } int mid=l+r>>1; init(o->ch[0],l,mid,num<<1), init(o->ch[1],mid+1,r,num<<1|1); Add_Edge(n+num,n+o->ch[0]->num,INF,0), Add_Edge(n+num,n+o->ch[1]->num,INF,0); return ; } void build(Node* o,int l,int r,int ord) { if(o->l==l && o->r==r) { Add_Edge(ord,n+o->num,1,0); return ; } int mid=o->l+o->r>>1; if(r<=mid) build(o->ch[0],l,r,ord); else if(l>mid) build(o->ch[1],l,r,ord); else build(o->ch[0],l,mid,ord), build(o->ch[1],mid+1,r,ord); return ; } int main() { memset(fir,-1,sizeof fir); scanf("%d",&n); T=n*5+1; init(root,1,n,1); for(int i=1,x,y,z;i<=n;++i) { scanf("%d%d%d",&x,&y,&z), --y; Add_Edge(S,i,1,-z); build(root,x,y,i); } Costflow(); printf("%d\n",-tot_cost); return 0; }
相关文章推荐
- BZOJ 4276 ONTAK2015 Bajtman i Okrągły Robin 费用流+线段树优化构图
- 【BZOJ4276】[ONTAK2015]Bajtman i Okrągły Robin 线段树优化建图+费用流
- 【线段树优化建图+费用流】BZOJ4276 [ONTAK2015]Bajtman i Okrągły Robin
- BZOJ 4276: [ONTAK2015]Bajtman i Okrągły Robin [线段树优化建边]
- bzoj 4276: [ONTAK2015]Bajtman i Okrągły Robin 线段树优化建图+费用流
- bzoj 4276: [ONTAK2015]Bajtman i Okrągły Robin【线段树+最大费用最大流】
- BZOJ_4276_[ONTAK2015]Bajtman i Okrągły Robin_线段树优化建图+最大费用最大流
- [bzoj4276][ONTAK2015]Bajtman i Okrągły Robin
- [二分图匹配 贪心] BZOJ 4276 [ONTAK2015]Bajtman i Okrągły Robin && BZOJ 2034 [2009国家集训队]最大收益
- 【bzoj4276】【ONTAK2015】【Bajtman i Okrągły Robin】【二分图匹配】
- BZOJ 4276: [ONTAK2015]Bajtman i Okrągły Robin
- BZOJ 4276([ONTAK2015]Bajtman i Okrągły Robin-线段树构图费用流)
- BZOJ 4276: [ONTAK2015]Bajtman i Okrągły Robin|贪心|匈牙利
- BZOJ4276 : [ONTAK2015]Bajtman i Okrągły Robin
- 4276: [ONTAK2015]Bajtman i Okrągły Robin 费用流+线段树优化建图/贪心
- 【线段树优化建图+费用流Spfa增广】BZOJ4276(ONTAK2015)[Bajtman i Okrągły Robin]题解
- 4276: [ONTAK2015]Bajtman i Okrągły Robin 线段树优化费用流
- 4276: [ONTAK2015]Bajtman i Okrągły Robin
- [ONTAK2015]Bajtman i Okrągły Robin
- BZOJ4276: [ONTAK2015]Bajtman i Okrągły Robin