BZOJ4276: [ONTAK2015]Bajtman i Okrągły Robin
2017-08-19 08:48
357 查看
BZOJ4276: [ONTAK2015]Bajtman i Okrągły Robin
费用流·线段树优化建图题解:
有一个用费用流的显然做法,可惜边是O(n2)级别的。这时就要用到线段树优化建图啦!
一个强盗的区间拆成log个线段树上的区间,向对应的线段树节点连边,线段树上的非叶子向儿子连边,叶子向T连容量为1的边,最后S向每个强盗连边,容量1,费用w[i].
Code:
#include <iostream> #include <cstring> #include <cstdio> #include <queue> #define D(x) cout<<#x<<" = "<<x<<" " #define E cout<<endl using namespace std; const int maxn = 25005; const int INF = 0x3f3f3f3f; int n, L[maxn], R[maxn], W[maxn], maxt; int S, T, dis[maxn], pre[maxn]; bool vis[maxn]; struct Edge{ int from,to,next,cap,flow,cost; } e[maxn*20]; int head[maxn], ec=1; void add(int a,int b,int cap,int cost){ ec++; e[ec].cap=cap; e[ec].flow=0; e[ec].cost=cost; e[ec].from=a; e[ec].to=b; e[ec].next=head[a]; head[a]=ec; } void add2(int a,int b,int cap,int cost){ // D(a); D(b); D(cap); D(cost); E; add(a,b,cap,cost); add(b,a,0,-cost); } bool spfa(){ memset(dis,0x3f,sizeof(dis)); memset(vis,false,sizeof(vis)); queue<int> q; q.push(S); vis[S]=true; dis[S]=0; while(!q.empty()){ int u=q.front(); q.pop(); vis[u]=false; for(int i=head[u];i;i=e[i].next){ if(e[i].cap == e[i].flow) continue; int v=e[i].to; if(dis[v] > dis[u]+e[i].cost){ dis[v]=dis[u]+e[i].cost; pre[v]=i; if(!vis[v]){ vis[v]=true; q.push(v); } } } } return dis[T]!=INF; } int mxf(){ int ans=0; while(spfa()){ int a=INF; for(int i=pre[T];i;i=pre[e[i].from]) a=min(a, e[i].cap-e[i].flow); for(int i=pre[T];i;i=pre[e[i].from]){ ans+=e[i].cost*a; e[i].flow+=a; e[i^1].flow-=a; } // D(a); D(ans); E; } return ans; } void build(int x,int l,int r){ if(l!=r){ add2(x+n,x*2+n,INF,0); add2(x+n,x*2+1+n,INF,0); int mid=(l+r)>>1; build(x*2,l,mid); build(x*2+1,mid+1,r); } else{ add2(x+n,T,1,0); } } void query(int x,int l,int r,int ql,int qr,int id){ if(ql<=l && r<=qr) add2(id,x+n,1,0); else{ int mid=(l+r)>>1; if(ql<=mid) query(x*2,l,mid,ql,qr,id); if(qr>mid) query(x*2+1,mid+1,r,ql,qr,id); } } void init(){ memset(head,0,sizeof(head)); ec=1; S=maxn-5; T=S+1; build(1,1,maxt); for(int i=1;i<=n;i++){ query(1,1,maxt,L[i],R[i],i); } for(int i=1;i<=n;i++){ add2(S,i,1,-W[i]); } } int main(){ freopen("a.in","r",stdin); scanf("%d",&n); for(int i=1;i<=n;i++){ scanf("%d%d%d",&L[i],&R[i],&W[i]); R[i]--; maxt=max(maxt,R[i]); } init(); int ans=-mxf(); printf("%d\n",ans); }
相关文章推荐
- Bzoj4276 [ONTAK2015]Bajtman i Okrągły Robin
- 【线段树优化建图+费用流Spfa增广】BZOJ4276(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 费用流+线段树优化建图/贪心
- 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【线段树+最大费用最大流】
- BZOJ4276 : [ONTAK2015]Bajtman i Okrągły Robin
- [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
- 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国家集训队]最大收益