[bzoj3218]a + b Problem 网络流+主席树优化建图

3218: a + b Problem

Time Limit: 20 Sec  Memory Limit: 40 MB
Submit: 2229  Solved: 836
[Submit][Status][Discuss]

Description

Input

 

Output

 

Sample Input

10
0 1 7 3 9 2
7 4 0 9 10 5
1 0 4 2 10 2
7 9 1 5 7 2
6 3 5 3 6 2
6 6 4 1 8 1
6 1 6 0 6 5
2 2 5 0 9 3
5 1 3 0 2 5
5 6 7 1 1 2

Sample Output

55

HINT

 

Source

此题是一个选择性问题,明显是用网络流来解决。

考虑没有p限制,这是一个最大权闭合子图问题。

从S像每一个i连一条bi的边,从i向T连一条wi的边,跑最小割即可。

对于p限制,我们要体现出要是没割wi且存在一个aj使得他在li-ri之间,他就要变得奇怪。

所以我们可以将i拆成两个点i,i+n。

从i向i+n连一条容量为pi的边,从i+n向每一个满足条件的j连一条inf的边。

由于n为5000,考虑使用主席树优化建图即可解决。

 1 #include<iostream>
 2 #include<cstring>
 3 #include<cstdlib>
 4 #include<cstdio>
 5 #include<cmath>
 6 #include<algorithm>
 7 #define maxm 1000005
 8 #define maxn 5005
 9 #define inf 999999999
10 using namespace std;
11 inline int read() {
12     int x=0,f=1;char ch=getchar();
13     for(;!isdigit(ch);ch=getchar()) if(ch=='-') f=-1;
14     for(;isdigit(ch);ch=getchar()) x=x*10+ch-'0';
15     return x*f;
16 }
17 int ans=0,n;
18 struct Edge {int to,nxt,c;}e[maxm*2];
19 int head[maxn*20],cnt;
20 inline void add(int u,int v,int c) {e[cnt].nxt=head[u];e[cnt].to=v;e[cnt].c=c;head[u]=cnt++;swap(u,v);c=0;e[cnt].nxt=head[u];e[cnt].to=v;e[cnt].c=c;head[u]=cnt++;}
21 int a[maxn],b[maxn],w[maxn],l[maxn],r[maxn],p[maxn],hsh[maxn*20],sum;
22 int S,T,sz;
23 struct seg {int l,r;}t[maxn*20];
24 int rt[maxn*20];
25 inline void query(int l,int r,int x,int L,int R,int point) {
26     if(!x||L>r||R<l) return;
27     if(L<=l&&R>=r) {add(point,x,inf);return;}
28     int mid=(l+r)>>1;
29     if(L<=mid) query(l,mid,t[x].l,L,R,point);
30     if(R>mid) query(mid+1,r,t[x].r,L,R,point);
31     return;
32 }
33 inline void insert(int l,int r,int &x,int pre,int pos,int point) {
34     x=++sz;
35     if(l==r&&pre>0) add(x,pre,inf);
36     if(l==r) {add(x,point,inf);return;}
37     t[x]=t[pre];
38     int mid=(l+r)>>1;
39     if(pos<=mid) insert(l,mid,t[x].l,t[pre].l,pos,point);
40     else insert(mid+1,r,t[x].r,t[pre].r,pos,point);
41     if(t[x].l) add(x,t[x].l,inf);
42     if(t[x].r) add(x,t[x].r,inf);
43 }
44 int q[maxn*20],dis[maxn*20];
45 inline bool bfs() {
46     for(int i=0;i<=sz;i++) dis[i]=-100000000;
47     int hd=0,tl=1;
48     q[0]=T;dis[T]=0;
49     while(hd!=tl) {
50         int now=q[hd++];if(hd==100000) hd=0;
51         for(int i=head[now];i>=0;i=e[i].nxt) {
52             int to=e[i].to;if(dis[to]>-100000000||!e[i^1].c) continue;
53             dis[to]=dis[now]-1;q[tl++]=to;
54             if(tl==100000) tl=0;
55         }
56     }
57     return dis[S]>-100000000;
58 }
59 inline int dfs(int x,int mxf) {
60     if(!mxf||x==T) return mxf;
61     int nf=0;
62     for(int i=head[x];i>=0;i=e[i].nxt) {
63         int to=e[i].to;
64         if(e[i].c&&dis[to]==dis[x]+1) {
65             int f=dfs(to,min(mxf,e[i].c));
66             mxf-=f;e[i].c-=f;
67             e[i^1].c+=f;nf+=f;
68             if(!mxf) break;
69         }
70     }
71     if(!nf) dis[x]=-100000000;
72     return nf; 
73 }
74 inline void dinic() {while(bfs()) ans-=dfs(S,inf);}
75 int main() {
76     memset(head,-1,sizeof(head));
77     n=read();S=2*n+1,T=2*n+2;sz=T;
78     for(int i=1;i<=n;i++) {
79         a[i]=read(),b[i]=read(),w[i]=read(),l[i]=read(),r[i]=read(),p[i]=read();
80         hsh[++sum]=a[i];hsh[++sum]=l[i];hsh[++sum]=r[i];
81         ans+=w[i]+b[i];
82     }
83     sort(hsh+1,hsh+sum+1);sum=unique(hsh+1,hsh+sum+1)-hsh-1;
84     for(int i=1;i<=n;i++) {
85         a[i]=lower_bound(hsh+1,hsh+sum+1,a[i])-hsh;
86         l[i]=lower_bound(hsh+1,hsh+sum+1,l[i])-hsh;
87         r[i]=lower_bound(hsh+1,hsh+sum+1,r[i])-hsh;
88         add(S,i,b[i]);add(i,i+n,p[i]);add(i,T,w[i]);
89     }
90     for(int i=1;i<=n;i++) {
91         if(i>1) query(1,sum,rt[i-1],l[i],r[i],i+n);
92         insert(1,sum,rt[i],rt[i-1],a[i],i);
93     }
94     dinic();printf("%d
",ans);
95 }
View Code
原文地址:https://www.cnblogs.com/wls001/p/9682944.html