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 }

 

你可能感兴趣的:(poj)