【bzoj3218】a+b Problem 最小割+主席树

数据范围:$n≤5000$,$a,l,r≤10^9$,$b,w,p≤2\times 10^5$。

 

我们考虑一种暴力的最小割做法:

首先令$sum=\sum\limits_{i=1}^{n} b_i+w_i$

 

我们建一个图:

$S->i$,边权为$w_i$

$i->T$,边权为$b_i$

$i->i'$,边权为$p_i$

$j->i'$,边权为$∞$,(这里的i和j需要满足题目中的i,j限制)

然后我们对这个图跑一遍最小割,将$sum$减去这个值输出就是答案了。

这么建图总共需要$2n+2$个点,$O(n^2)$条边

 1 #include<bits/stdc++.h>
 2 #define M 1000005
 3 #define N 150005
 4 #define INF 19890604
 5 using namespace std;
 6 
 7 struct edge{int u,v,next;}e[M]={0}; int head[N]={0},use=0;
 8 void add(int x,int y,int z){e[use].u=y;e[use].v=z;e[use].next=head[x];head[x]=use++;}
 9 void ADD(int x,int y,int z){add(x,y,z); add(y,x,0);}
10 
11 int dis[N]={0},S,T; queue<int> q;
12 
13 bool bfs(){
14     memset(dis,0,sizeof(dis));
15     q.push(S); dis[S]=1;
16     while(!q.empty()){
17         int u=q.front(); q.pop();
18         for(int i=head[u];~i;i=e[i].next)
19         if(e[i].v&&dis[e[i].u]==0){
20             dis[e[i].u]=dis[u]+1;
21             q.push(e[i].u);
22         }
23     }
24     return dis[T];
25 }
26 
27 int dfs(int x,int flow){
28     if(x==T) return flow; int sum=0;
29     for(int i=head[x];~i;i=e[i].next)
30     if(e[i].v&&dis[x]+1==dis[e[i].u]){
31         int k=dfs(e[i].u,min(flow,e[i].v));
32         e[i].v-=k; e[i^1].v+=k;
33         sum+=k; flow-=k;
34         if(flow==0) return sum;
35     }
36     if(flow==0) dis[x]=-1;
37     return sum;
38 }
39 
40 int dinic(){
41     int res=0; 
42     while(bfs()) 
43     res+=dfs(S,1<<30); 
44 return res;}
45 
46 int n,sum=0;
47 int a[N]={0},b[N]={0},w[N]={0},l[N]={0},r[N]={0},p[N]={0},ok[N]={0};
48 
49 int main(){
50     scanf("%d",&n);
51     for(int i=1;i<=n;i++){
52         scanf("%d%d%d%d%d%d",a+i,b+i,w+i,l+i,r+i,p+i);
53         sum+=b[i]+w[i];
54     }
55     S=0,T=2*n+1;
56     memset(head,-1,sizeof(head));
57     for(int i=1;i<=n;i++) ADD(S,i,w[i]),ADD(i,T,b[i]),ADD(i+n,i,p[i]);
58     for(int i=1;i<=n;i++) for(int j=1;j<i;j++)
59     if(l[i]<=a[j]&&a[j]<=r[i])
60     ADD(j,i+n,INF);
61     cout<<sum-dinic()<<endl;
62 }    
暴力

相关文章: