zoukankan      html  css  js  c++  java
  • poj3680 区间图的最大权独立集问题

      附上题目链接:http://poj.org/problem?id=3680

      题意大概是这样, 给你n个开区间, 每个开区间有一些权重, 现在从这些开区间里面选择一些区间, 使得每个点不被覆盖超过k次, 问你所能得到的最大权重是多少? 题目分析见挑战p247, 这里我们附上另一份题解:

    1. /* 
    2. 都说这题是构图很巧的好题~我也赞一个吧,虽然我没有想到。 
    3. 说说我的思考过程吧。 
    4. 做这题是因为这题在网络流的分类里面,自然一开始就想构图了~ 
    5. (1)能作为结点的东西的只有两个,区间和端点,区间没什么道理,以端点做结点的话,离散化是要的; 
    6. (2)k限制流量用,段的权值与流量没什么关系,是一种费用性的东西,所以是费用流; 
    7. (3)考虑到区间包含连续的点,我画了一个S->1->2->...->T的线图(流量限制为k,费用暂时为0),并尝试对区间(a,b)(权值为w)加边add(S,a,w,1)和add(b,T,w,1),但又捣乱了流量关系,于是继续凌乱中~ 
    8. 在哪个路口乱了咧?没理清楚的流量关系~差一点了! 
    9. 建图改成代码中的那样后,即add(S,1,0,k),add(cnt,T,0,k),add(i,i+1,0,k),add(a,b,-w,1),a到b的流量一旦形成,a和b之间的点因为在a点之后,流量自然会超限,b之后的点流量也不会受影响,太可爱了!如果这个完整的思考过程属于我就爽了  代码如下:
    10. #include <cstdio>
      #include <algorithm>
      #include <vector>
      #include <queue>
      #include <cstring>
      #include <iostream>
      
      using namespace std;
      const int inf = 0x3f3f3f3f;
      const int maxn = 450;
      
      struct Edge { int from, to, cap, flow, cost; };
      vector<Edge> edges;
      vector<int> G[maxn];
      int inque[maxn];   //spfa
      int d[maxn];    //源点到当前点的最短路
      int p[maxn];    //入弧编号
      int a[maxn];    //可改进量
      
      void init(int n)
      {
          for(int i=0; i<=n; i++) G[i].clear();
          edges.clear();
      }
      
      void add_edge(int from, int to, int cap, int cost)
      {
          edges.push_back((Edge){from, to, cap, 0, cost});
          edges.push_back((Edge){to, from, 0, 0, -cost});
          int m = edges.size();
          G[from].push_back(m-2);
          G[to].push_back(m-1);
      }
      
      bool spfa(int s, int t, int &flow, long long &cost)
      {
          memset(d, 0x3f, sizeof(d));
          memset(inque, 0, sizeof(inque));
          d[s] = 0; inque[s] = 1;
          a[s] = inf; p[s] = 0;
          queue<int> que;
          que.push(s);
          while(!que.empty()){
              int u = que.front(); que.pop();
              inque[u] = 0;
              for(int i=0; i<G[u].size(); i++){
                  Edge e = edges[G[u][i]];
                  if(e.cap>e.flow && d[e.to]>d[u]+e.cost){
                      d[e.to] = d[u] + e.cost;
                      if(!inque[e.to]) que.push(e.to), inque[e.to]=1;
                      p[e.to] = G[u][i];   //e.to的入弧编号
                      a[e.to] = min(a[u], e.cap-e.flow);   //更新可改进量
                  }
              }
          }
          if(d[t] == inf) return false;
          flow += a[t];
          cost += (long long)a[t]*(long long)d[t];
          for(int u=t; u!=s; u=edges[p[u]].from){
              edges[p[u]].flow += a[t];
              edges[p[u]^1].flow -= a[t];
          }
          return true;
      }
      
      int MCMF(int s, int t, long long &cost)
      {
          int flow = 0; cost = 0;
          while(spfa(s, t, flow, cost));
          return flow;
      }
      
      int aa[250], bb[250], ww[250];
      vector<int> x;
      
      int main() {
          int T;
          scanf("%d", &T);
          while(T--) {
              int N, K;
              scanf("%d%d", &N, &K);
              x.clear();
              for(int i=0; i<N; i++) {
                  int a, b, w;
                  scanf("%d%d%d", &a, &b, &w);
                  x.push_back(a);
                  x.push_back(b);
                  aa[i] = a;
                  bb[i] = b;
                  ww[i] = w;
              }
              sort(x.begin(), x.end());
              x.erase(unique(x.begin(), x.end()), x.end());
              //debug
              //for(int i=0; i<x.size(); i++)
              //    cout<<x[i]<<' ';
              //cout<<endl;
              int m = x.size();
              int s = m, t = m+1;
              init(m+1);
              add_edge(s, 0, K, 0);
              add_edge(m-1, t, K, 0);
              for(int i=0; i+1<x.size(); i++) {
                  add_edge(i, i+1, K, 0);
              }
              for(int i=0; i<N; i++) {
                  int u = find(x.begin(), x.end(), aa[i]) - x.begin();
                  int v = find(x.begin(), x.end(), bb[i]) - x.begin();
                  add_edge(u, v, 1, -ww[i]);
              }
              long long cost = 0;
              MCMF(s, t, cost);
              cout<<-cost<<endl;
          }
          return 0;
      }
  • 相关阅读:
    vue中 key 值的作用
    v-on可以监听多个方法吗?
    vue常用的修饰符
    v-if和v-show的区别
    Vue和其他框架的区别
    Vue面试题总结——目录
    vue是一个渐进式的框架,我是这么理解的
    原生JS封装创建多级菜单函数
    如何使用mongodb(建立原型,连接数据库)
    Hive 的安装与配置
  • 原文地址:https://www.cnblogs.com/xingxing1024/p/5490293.html
Copyright © 2011-2022 走看看