POJ 3680 最大费用流
题意:
有N个整数区间,每个区间有一个权值,从中取一些区间,使得任意整数点的重叠数不大于K,并且这些区间的总权值最大。
ps:区间不能重复选择!
题解:
经典的建图,表示自己想了好多都没有想到,最后还是lyd给我讲的。。。
先离散化,建立边(i,i+1,k,0),i到i+1容量k费用0的边;边(i,j,1,w),i和j为给定区间的左右端点,容量1费用0,最大费用流即可~
View Code
1 #include <iostream> 2 #include <algorithm> 3 #include <cstdlib> 4 #include <cstdio> 5 #include <cstring> 6 7 #define M 10000 8 #define N 800 9 #define INF 1E9 10 11 using namespace std; 12 13 int to[M],next[M],head[N],len[M],pr[M],val[N],pre[N],q[M],dis[N],son[N]; 14 bool vis[N]; 15 int S,T,bcnt,cnt,tot,n,k,cas; 16 17 struct PX 18 { 19 int b,w,tb,bh; 20 }px[N]; 21 22 inline bool cmp(const PX &a,const PX &b) 23 { 24 return a.b<b.b; 25 } 26 27 inline bool cmpbh(const PX &a,const PX &b) 28 { 29 if(a.bh==b.bh) return a.tb<b.tb; 30 return a.bh<b.bh; 31 } 32 33 inline void add(int u,int v,int r,int w) 34 { 35 to[tot]=v; len[tot]=r; pr[tot]=w; next[tot]=head[u]; head[u]=tot++; 36 to[tot]=u; len[tot]=0; pr[tot]=-w; next[tot]=head[v]; head[v]=tot++; 37 } 38 39 inline void read() 40 { 41 memset(head,-1,sizeof head); tot=0; 42 scanf("%d%d",&n,&k); 43 cnt=0; 44 for(int i=1,a,b;i<=n;i++) 45 { 46 scanf("%d%d%d",&a,&b,&val[i]); 47 cnt++; px[cnt].b=a; px[cnt].bh=i; 48 cnt++; px[cnt].b=b; px[cnt].bh=i; 49 } 50 sort(px+1,px+1+cnt,cmp); 51 bcnt=0; 52 for(int i=1;i<=cnt;i++) 53 { 54 if(px[i].b!=px[i-1].b) px[i].tb=++bcnt; 55 else px[i].tb=bcnt; 56 } 57 sort(px+1,px+1+cnt,cmpbh); 58 } 59 60 inline bool spfa() 61 { 62 for(int i=0;i<=T;i++) dis[i]=-INF; 63 memset(pre,-1,sizeof pre); 64 int h=1,t=2,sta; 65 q[1]=S; vis[S]=true; dis[S]=0; 66 while(h<t) 67 { 68 sta=q[h++]; vis[sta]=false; 69 for(int i=head[sta];~i;i=next[i]) 70 if(len[i]>0&&dis[to[i]]<dis[sta]+pr[i]) 71 { 72 dis[to[i]]=dis[sta]+pr[i]; 73 pre[to[i]]=i; 74 if(!vis[to[i]]) vis[to[i]]=true,q[t++]=to[i]; 75 } 76 } 77 return pre[T]!=-1; 78 } 79 80 inline void updata() 81 { 82 for(int i=pre[T];~i;i=pre[to[i^1]]) 83 { 84 len[i]-=1; len[i^1]+=1; 85 } 86 } 87 88 inline void go() 89 { 90 S=0; T=bcnt+1; 91 for(int i=0;i<=bcnt;i++) add(i,i+1,k,0); 92 for(int i=1;i<=cnt;i+=2) add(px[i].tb,px[i+1].tb,1,val[px[i].bh]); 93 int ans=0; 94 while(spfa()) ans+=dis[T],updata(); 95 printf("%d\n",ans); 96 } 97 98 int main() 99 { 100 scanf("%d",&cas); 101 while(cas--) read(),go(); 102 return 0; 103 }
没有人能阻止我前进的步伐,除了我自己!