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 }
没有人能阻止我前进的步伐,除了我自己!
原文地址:https://www.cnblogs.com/proverbs/p/2848206.html