zoukankan      html  css  js  c++  java
  • POJ 3680 Intervals

    题意

    有n个线段((a_i,b_i)),每个线段有一个权值(w_i)。要求选若干个线段,使得数轴上每个点至多被k个线段包含。

    建图

    可以把权值取负值作为费用求费用流,这题有两种建图方式

    1. 离散化数据,对每个点i连一条i到i+1的边,流量为k,费用为0。对于所有线段连一条(a_i)(b_i)的边,流量为1,费用为-(w_i)。那么,对每个点可以选择以这个点为起点的线段或者不选,如果选了就需要花费1个流量,且直到线段终点都只剩下了k-1个流量,所以可以确保每一个点最多被k条线段覆盖。

    2. 考虑把线段覆盖改为找k个不相交的线段集合。把每个线段拆成两个点,这样就可以对所有不相交的线段进行连边。并且对每个线段的起点终点连边(费用为-w),源点对线段起点连边,线段终点对汇点连边。这样线段集合就表示为了一条增广路。最后在源点或汇点加一个限制(流量为k的边)就可以了。

    代码

    1. #include<vector>
      #include<algorithm>
      #include<cstdio>
      #include<cstring>
      #include<queue>
      using namespace std;
      const int maxn=200+5;
      int a[maxn],b[maxn],ww[maxn];
      vector<int>vec;
      
      struct Edge{
          int v,w,c,next;
      }edge[maxn*6];
      int head[maxn*2],ecnt;
      void add(int u,int v,int w,int c)
      {
          edge[ecnt]=(Edge){v,w,c,head[u]};
          head[u]=ecnt++;
      }
      
      const int inf=0x3f3f3f3f;
      int S,T;
      int fa[maxn*2],fai[maxn*2];
      int dis[maxn*2], vis[maxn*2];
      bool spfa()
      {
          memset(dis,0x3f,sizeof(dis));
          queue<int>q;
          dis[S]=0;
          for(q.push(S);!q.empty();q.pop())
          {
              int u=q.front();
              vis[u]=0;
              for(int i=head[u];i!=-1;i=edge[i].next)
              {
                  int v=edge[i].v;
                  if(!edge[i].w)continue;
                  if(dis[v]>dis[u]+edge[i].c)
                  {
                      dis[v]=dis[u]+edge[i].c;
                      fa[v]=u;
                      fai[v]=i;
                      if(!vis[v])
                      {
                          vis[v]=1;
                          q.push(v);
                      }
                  }
              }
          }
          return dis[T]!=inf;
      }
      
      int cost()
      {
          int ans=0,flow=inf;
          for(int u=T;u!=S;u=fa[u])
              flow=min(flow,edge[fai[u]].w);
          for(int u=T;u!=S;u=fa[u])
          {
              edge[fai[u]].w-=flow;
              edge[fai[u]^1].w+=flow;
              ans+=flow*edge[fai[u]].c;
          }
          return ans;
      }
      
      int main()
      {
          int ca;
          scanf("%d",&ca);
          while(ca--)
          {
              int N,K;
              vec.clear();
              memset(head,-1,sizeof(head));
              ecnt=0;
              scanf("%d%d",&N,&K);
              for(int i=1;i<=N;i++)
              {
                  scanf("%d%d%d",&a[i],&b[i],&ww[i]);
                  vec.push_back(a[i]);
                  vec.push_back(b[i]);
              }
              sort(vec.begin(),vec.end());
              int n=unique(vec.begin(),vec.end())-vec.begin();
              vec.resize(n);
              for(int i=1;i<=N;i++)
              {
                  a[i]=lower_bound(vec.begin(),vec.end(),a[i])-vec.begin()+1;
                  b[i]=lower_bound(vec.begin(),vec.end(),b[i])-vec.begin()+1;
      
                  add(a[i],b[i],1,-ww[i]);
                  add(b[i],a[i],0,ww[i]);
              }
              for(int i=0;i<=n;i++)
              {
                  add(i,i+1,K,0);
                  add(i+1,i,0,0);
              }
              S=0;T=n+1;
              int ans=0;
              while(spfa())
                  ans+=cost();
              printf("%d
      ",-ans);
          }
          return 0;
      }
      
    2. #include<vector>
      #include<algorithm>
      #include<cstdio>
      #include<cstring>
      #include<queue>
      using namespace std;
      const int maxn=200+5;
      int a[maxn],b[maxn],ww[maxn];
      
      struct Edge{
          int v,w,c,next;
      }edge[maxn*maxn*2];
      int head[maxn*2],ecnt;
      void add(int u,int v,int w,int c)
      {
          edge[ecnt]=(Edge){v,w,c,head[u]};
          head[u]=ecnt++;
          edge[ecnt]=(Edge){u,0,-c,head[v]};
          head[v]=ecnt++;
      }
      
      const int inf=0x3f3f3f3f;
      int S,T;
      int fa[maxn*2],fai[maxn*2];
      int dis[maxn*2], vis[maxn*2];
      bool spfa()
      {
          memset(dis,0x3f,sizeof(dis));
          queue<int>q;
          dis[S]=0;
          for(q.push(S);!q.empty();q.pop())
          {
              int u=q.front();
              vis[u]=0;
              for(int i=head[u];i!=-1;i=edge[i].next)
              {
                  int v=edge[i].v;
                  if(!edge[i].w)continue;
                  if(dis[v]>dis[u]+edge[i].c)
                  {
                      dis[v]=dis[u]+edge[i].c;
                      fa[v]=u;
                      fai[v]=i;
                      if(!vis[v])
                      {
                          vis[v]=1;
                          q.push(v);
                      }
                  }
              }
          }
          return dis[T]!=inf;
      }
      
      int cost()
      {
          int ans=0,flow=inf;
          for(int u=T;u!=S;u=fa[u])
              flow=min(flow,edge[fai[u]].w);
          for(int u=T;u!=S;u=fa[u])
          {
              edge[fai[u]].w-=flow;
              edge[fai[u]^1].w+=flow;
              ans+=flow*edge[fai[u]].c;
          }
          return ans;
      }
      
      int main()
      {
          int ca;
          scanf("%d",&ca);
          while(ca--)
          {
              int N,K;
              memset(head,-1,sizeof(head));
              ecnt=0;
              scanf("%d%d",&N,&K);
              S=0,T=2*N+2;
              for(int i=1;i<=N;i++)
              {
                  scanf("%d%d%d",&a[i],&b[i],&ww[i]);
                  add(i*2,i*2+1,1,-ww[i]);
                  //add(i*2,i*2+1,inf,0);
                  add(S+1,i*2,1,0);
                  add(i*2+1,T,1,0);
              }
              add(S,S+1,K,0);
              for(int i=1;i<=N;i++)
                  for(int j=1;j<=N;j++)
                      if(b[i]<=a[j])
                          add(2*i+1,2*j,inf,0);
              int ans=0;
              while(spfa())
                  ans+=cost();
              printf("%d
      ",-ans);
          }
          return 0;
      }
      
  • 相关阅读:
    Linux 学习 step by step (2)
    公共建筑能耗监测平台的GPRS通讯服务器的开发方法分享
    幸福框架:可扩展的、动态的、万能的 编号生成器
    C++ Data Member内存布局
    .NET程序集强命名删除与再签名技术 源代码剖析
    hdu 2191(多重背包)
    五种情况下会刷新控件状态(刷新所有子FWinControls的显示)——从DFM读取数据时、新增加子控件时、重新创建当前控件的句柄时、设置父控件时、显示状态被改变时
    终于懂了:Delphi消息的Result域出现的原因——要代替回调函数的返回值!(MakeObjectInstance不会帮助处理(接收)消息回调函数的返回值)
    Firemonkey实现Mac OS程序中内嵌浏览器的功能(自己动手翻译,调用苹果提供的webkit框架)
    感悟:市场经济看得就是主观能动性,有则富贵可及,无则无限趋于零
  • 原文地址:https://www.cnblogs.com/intmian/p/12198798.html
Copyright © 2011-2022 走看看