zoukankan      html  css  js  c++  java
  • 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 }
    没有人能阻止我前进的步伐,除了我自己!
  • 相关阅读:
    C++ Low level performance optimize
    简单find命令的实现
    数据结构学习之栈
    随机数的生成
    数据结构学习(一)
    C复习---动态内存分配
    (转)虚拟文件系统(VFS)浅析
    (转) 中断处理程序&中断服务例程
    Gradle系列教程之依赖管理
    Gradle系列教程之依赖管理
  • 原文地址:https://www.cnblogs.com/proverbs/p/2848206.html
Copyright © 2011-2022 走看看