The main idea of the topic: ... See for yourself
From the source point, the two flows to the meeting point are the sides of A and b respectively, and the maximum flow is a+b.
Code:
#include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #define M 10# Define S 1#define T 2#define INF 0x3f3f3f3fusing namespace std;struct abcd{int to,f,next;} Table[100];int head[m],tot=1;void Add (int x,int y,int z) {table[++tot].to=y;table[tot].f=z;table[tot].next=head[x]; Head[x]=tot;} void Link (int x,int y,int z) {Add (x, y, z); ADD (y,x,0);} namespace max_flow{int dpt[m]; BOOL BFS () {static int q[m]; int i,r=0,h=0; memset (dpt,-1,sizeof DPT); Q[++r]=s;dpt[s]=1; while (r!=h) {int x=q[++h]; for (I=head[x];i;i=table[i].next) if (table[i].f&&!~dpt[table[i].to]) { dpt[table[i].to]=dpt[x]+1; q[++r]=table[i].to; if (table[i].to==t) return true; }} return false; } int dinic (int x,int flow) {int i,left=flow; if (x==t) return flow; for (I=head[x];i&&left;i=table[i].next) if (table[i].f&&dpt[table[i].to]==dpt[x]+1) {int Temp=dinic (table[i].to,min (LEFT,TABLE[I].F)); if (!temp) dpt[table[i].to]=-1; Left-=temp; Table[i].f-=temp; Table[i^1].f+=temp; } return flow-left; }}int Main () {using namespace Max_flow;int i,x,ans=0;for (i=1;i<=2;i++) scanf ("%d", &x), Link (S,t,x), while (BFS () ) Ans+=dinic (s,inf); Cout<<ans<<endl;return 0;}
。。。 The one above is a joke.
First, consider some simple practices
Each point I is split into two points I and I ', I ' to I even a flow for the side of P
An edge with a flow of W from S to I with a flow of b from I to t
If j selected White point I selected black point I will become odd ♂ strange, from J to I ' even a flow to the edge of the INF
This ensures that if J chooses white, I either chooses white, or becomes odd ♂ strange.
However, the j->i ' number of sides can reach O (n^2).
We can consider building a tree of weight segments from J to the corresponding leaf nodes, from the I ' covered interval to the I ' Edge
But in doing so, we ignore the j<i condition.
So we're going to change this segment tree to a tree of durable segments.
Each new chain, from the previous version of each point and point I to the new link node edge
Then go to the previous version to query the corresponding interval and connect the edge can
#include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #define M 200200# Define S 0#define T 200199#define INF 0x3f3f3f3f#define P1 (x) ((x) *2-1) #define P2 (x) ((x) <<1) using namespace Std;int N,m,cnt;long long ans;namespace max_flow{struct abcd{int To,f,next;} Table[1001001];int head[m],tot=1;int dpt[m];void Add (int x,int y,int z) {Table[++tot].to=y;table[tot].f=z;table[tot]. Next=head[x];head[x]=tot;} void Link (int x,int y,int z) {Add (x, y, z); ADD (y,x,0);} BOOL BFS () {static int q[m];int i,r=0,h=0;memset (dpt,-1,sizeof DPT);DP t[s]=1;q[++r]=s;while (r!=h) {int x=q[++h];for (i= Head[x];i;i=table[i].next) if (table[i].f&&!~dpt[table[i].to]) {Dpt[table[i].to]=dpt[x]+1;q[++r]=table[i] . To;if (Table[i].to==t) return true;}} return false;} int dinic (int x,int flow) {int i,left=flow;if (x==t) return flow;for (I=head[x];i&&left;i=table[i].next) if ( table[i].f&&dpt[table[i].to]==dpt[x]+1) {int temp=dinic (table[i].to,min (LEFT,TABLE[I].F)); Left-=temp;tabLe[i].f-=temp;table[i^1].f+=temp;} if (left) Dpt[x]=-1;return Flow-left;} void DFS (int x) {static int v[m];v[x]=1;if (x<=n<<1) printf ("%d\n", x+1>>1); for (int i=head[x];i;i=table[ I].next) if (table[i].f&&!v[table[i].to]) DFS (table[i].to);} void Debug () {static int s[m],t[m];int i;for (i=head[s];i;i=table[i].next) if (table[i].to<=n<<1) s[table[i]. To+1>>1]= (table[i].f?-1:1); for (I=head[t];i;i=table[i].next) if (table[i].to<=n<<1) t[table[i].to+1 >>1]= (Table[i^1].f?-1:1), for (i=1;i<=n;i++) printf ("%d%d%d\n", I,s[i],t[i]);p UTS ("---------------------- ----------------");D FS (S);p UTS ("--------------------------------------"); for (I=HEAD[P2 (6)];i;i=table[i].next) if (TABLE[I].TO==P1 (6)) cout<<table[i].f<<endl;puts ("--------------------------------------");}} struct Segtree{segtree *ls,*rs;int val,num;void* operator new (size_t,segtree *_,segtree *__,int ___) {static Segtree memp Ool[m],*c=mempool; c->ls=_; c->rs=__; c->val=___; C->num=++cnt;returnC + +;} segtree* build_tree (int x,int y,int pos,int from) {using namespace Max_flow;int mid=x+y>>1; Segtree *re;if (x==y) re=new (0x0,0x0,val+1) Segtree;else if (pos<=mid) re=new (Ls->build_tree (X,mid,pos,from), RS , val+1) segtree;elsere=new (Ls,rs->build_tree (Mid+1,y,pos,from), val+1) Segtree; Link (From,re->num,inf); Link (Num,re->num,inf); return re;} void Get_ans (int x,int y,int l,int r,int to) {using namespace Max_flow;int mid=x+y>>1;if (!val) return; if (x==l&& Amp;y==r) {Link (num,to,inf); return;} if (r<=mid) Ls->get_ans (x,mid,l,r,to), else if (l>mid) Rs->get_ans (mid+1,y,l,r,to), Else Ls->get_ans (x, Mid,l,mid,to), Rs->get_ans (Mid+1,y,mid+1,r,to);}} *tree[5050];int Main () {using namespace Max_flow;int i,a,b,w,l,r,p;cin>>n;cnt=p2 (n); Tree[0]=new (0x0,0x0,0) Segtree;tree[0]->ls=tree[0]->rs=tree[0];for (i=1;i<=n;i++) {scanf ("%d%d%d%d%d%d", &a,&b,&w, &L,&R,&P); Link (S,P1 (i), W); Link (P1 (i), t,b); Tree[i]=tree[i-1]->build_tree (0,1000000000,A,P1 (i)); Tree[i-1]->get_ans (0,1000000000,L,R,P2 (i)); Link (P2 (i), P1 (i), p); ans+=w+b;} while (BFS ())) ans-=dinic (S,inf);//debug (); Cout<<ans<<endl;return 0;}
Bzoj 3218 A + B problem to persist segment tree + min cut