Description
Input
Output
Sample Input
1 4 40
2 4 10
2 3 30
1 3 20
Sample Output
建图:
·源点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 }