1. 程式人生 > >BZOJ 4276 [ONTAK2015]Bajtman i Okr?g?y Robin 費用流+線段樹優化建圖

BZOJ 4276 [ONTAK2015]Bajtman i Okr?g?y Robin 費用流+線段樹優化建圖

線段 namespace const 暴力 一個 turn 想要 r+ inf

Description

有n個強盜,其中第i個強盜會在[a[i],a[i]+1],[a[i]+1,a[i]+2],...,[b[i]-1,b[i]]這麽多段長度為1時間中選出一個時間進行搶劫,並計劃搶走c[i]元。作為保安,你在每一段長度為1的時間內最多只能制止一個強盜,那麽你最多可以挽回多少損失呢?

Input

第一行包含一個正整數n(1<=n<=5000),表示強盜的個數。 接下來n行,每行包含三個正整數a[i],b[i],c[i](1<=a[i]<b[i]<=5000,1<=c[i]<=10000),依次描述每一個強盜。

Output

輸出一個整數,即可以挽回的損失的最大值。

Sample Input

4
1 4 40
2 4 10
2 3 30
1 3 20

Sample Output

90
—————————————————————————————————————————————————— 分析: 很容易看出來一個網絡流的模型,但是暴力建圖一點未來都沒有...... 註意到強盜出現的時間是一個連續的區間,於是可以用線段樹來優化建圖。(好操作啊!)

建圖:
·源點S,匯點T。
·S向所有的小偷連邊,容量為1,費用為c[i]。
·所有小偷向對應區間連邊,容量為1,費用為0。
·線段樹的葉子向T連邊,容量為1,費用為0。
·線段樹中的點向其左右兒子連邊,容量為inf,費用為0。

最大流最大費就是答案。

But,卡常卡死我了......

註意兩點:

1、為了小常數,以後網絡流邊的結構體不要定義from這個變量。

2、當你想要卡常的時候,註意不要用結構體去套你的算法......全部東西都用數組吧......

3、我也不知道為什麽本機上最快的數組版本上去就T了?所以還是把過了的那個弄上來吧......

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cstring>
  4 #include<cstdlib>
  5 #include<algorithm>
  6 #include<cmath>
  7
#include<queue> 8 #include<set> 9 #include<map> 10 #include<vector> 11 #include<cctype> 12 #define inf 1e9 13 using namespace std; 14 const int MAXN=5005; 15 16 int N,a[MAXN],b[MAXN],c[MAXN],up,low=inf; 17 struct edge{ int to,next,cap,flow,cost; }E[300005]; 18 int n,s,t,np=0,first[15005],dist[15005],fl[15005]; 19 int mq[15005+5],front,rear; 20 bool inq[15005]; 21 void add_edge(int u,int v,int cap,int cost) 22 { 23 E[++np]=(edge){v,first[u],cap,0,cost}; 24 first[u]=np; 25 E[++np]=(edge){u,first[v],0,0,-cost}; 26 first[v]=np; 27 } 28 int MCMF(){ 29 int maxcost=0,now; 30 while(1){ 31 memset(dist,0,sizeof(dist)); 32 front=rear=0; 33 mq[rear++]=s,inq[s]=1; 34 while(front!=rear){ 35 int i=mq[front++]; if(front>15005) front=0; 36 inq[i]=0; 37 for(int p=first[i];p;p=E[p].next){ 38 int j=E[p].to; 39 if(E[p].cap>E[p].flow&&dist[i]+E[p].cost>dist[j]){ 40 dist[j]=dist[i]+E[p].cost; 41 fl[j]=p; 42 if(!inq[j]){ 43 mq[rear++]=j,inq[j]=1; 44 if(rear>15005) rear=0; 45 } 46 } 47 } 48 } 49 if(dist[t]<=0) break; 50 now=t,maxcost+=dist[t]; 51 while(now!=s){ 52 E[fl[now]].flow++,E[(fl[now]-1^1)+1].flow--; 53 now=E[(fl[now]-1^1)+1].to; 54 } 55 } 56 return maxcost; 57 } 58 59 int rt=0,np2=0,lc[10005],rc[10005]; 60 void build(int &now,int L,int R){ 61 now=++np2; 62 if(L==R){ 63 add_edge(now+N,t,1,0); 64 return; 65 } 66 int m=L+R>>1; 67 build(lc[now],L,m); 68 build(rc[now],m+1,R); 69 add_edge(now+N,lc[now]+N,inf,0); 70 add_edge(now+N,rc[now]+N,inf,0); 71 } 72 void update(int now,int L,int R,int A,int B,int id){ 73 if(A<=L&&R<=B){ 74 add_edge(id,now+N,1,0); 75 return; 76 } 77 int m=L+R>>1; 78 if(B<=m) update(lc[now],L,m,A,B,id); 79 else if(A>m) update(rc[now],m+1,R,A,B,id); 80 else update(lc[now],L,m,A,B,id),update(rc[now],m+1,R,A,B,id); 81 } 82 83 void _scanf(int &x) 84 { 85 x=0; 86 char ch=getchar(); 87 while(ch<0||ch>9) ch=getchar(); 88 while(ch>=0&&ch<=9) x=x*10+ch-0,ch=getchar(); 89 } 90 void data_in() 91 { 92 _scanf(N); 93 for(int i=1;i<=N;i++){ 94 _scanf(a[i]);_scanf(b[i]);_scanf(c[i]); 95 up=max(up,b[i]),low=min(low,a[i]); 96 } 97 } 98 void work() 99 { 100 n=2*(up-low)+N+5,s=n-1,t=n; 101 build(rt,low,up-1); 102 for(int i=1;i<=N;i++){ 103 update(rt,low,up-1,a[i],b[i]-1,i); 104 add_edge(s,i,1,c[i]); 105 } 106 printf("%d\n",MCMF()); 107 } 108 int main() 109 { 110 data_in(); 111 work(); 112 return 0; 113 }

BZOJ 4276 [ONTAK2015]Bajtman i Okr?g?y Robin 費用流+線段樹優化建圖