zoukankan      html  css  js  c++  java
  • POJ 1201 差分约束(集合最小元素个数)

    题意:
          给你一个集合,然后有如下输入,a ,b ,c表示在范围[a,b]里面有至少有c个元素,最后问你整个集合最少多少个元素。

    思路:
          和HDU1384一模一样,首先这个题目可以用差分约束来解决,是大于等于所以跑最长路(如果非要跑最短路建-权也可以),说下建图,首先我们把每个区间抽象出来,区间的两个端点之间的元素个数 [a ,b] = c 可以抽象成 点a,和点(b + 1)之间的距离 大于等于c,那么这样就可以把输入建进去了,还有个关键的地方就是题目的隐含条件,一般的查分约束的关键都是在于找隐含条件,这个题目的隐含条件就是相邻的

    两个点的元素个数 >= 0 && <= 1,其他的没啥了。


    #include<stdio.h>
    #include<string.h>
    #include<queue>
    
    #define N_node 55000
    #define N_edge 210000
    #define INF 100000000000000
    
    using namespace std;
    
    typedef struct
    { 
        int to ,next;
        __int64 cost;
    }STAR;
    
    STAR E[N_edge];
    int list[N_node] ,tot;
    __int64 s_x[N_node];
    
    void add(int a ,int b ,__int64 c)
    {
        E[++tot].to = b;
        E[tot].cost = c;
        E[tot].next = list[a];
        list[a] = tot;
    }
    
    bool spfa(int s ,int n)
    {
       for(int i = 0 ;i <= n ;i ++)
       s_x[i] = -INF;
       int mark[N_node] = {0};
       int in[N_node] = {0};
       s_x[s] = 0;
       mark[s] = in[s] = 1;
       queue<int>q;
       q.push(s);
       while(!q.empty())
       {
          int xin ,tou;
          tou = q.front();
          q.pop();
          mark[tou] = 0;
          for(int k = list[tou] ;k ;k = E[k].next)
          {
             xin = E[k].to;
             if(s_x[xin] < s_x[tou] + E[k].cost)
             {
                 s_x[xin] = s_x[tou] + E[k].cost;
                 if(!mark[xin])
                 {
                    mark[xin] = 1;
                    q.push(xin);
                    if(++in[xin] > n) return 0;
                 }
              }
            }
       }
       return 1;
    }
    
    int maxx(int x ,int y)
    {
        return x > y ? x : y;
    }
    int minn(int x ,int y)
    {
        return x < y ? x : y;
    }
    
    int main ()
    {
        int n ,a ,b ,i;
        __int64 c;
        while(~scanf("%d" ,&n))
        {
           memset(list ,0 ,sizeof(list));
           tot = 1;
           int Max = 0 ,Min = 100000000;
           for(i = 1 ;i <= n ;i ++)
           {
              scanf("%d %d %I64d" ,&a ,&b ,&c);
              b ++;
              add(a ,b ,c);
              Max = maxx(Max ,b);
              Min = minn(Min ,a);
           }
           for(i = Min ;i <= Max ;i ++)
           {
              add(i - 1 ,i ,0);
              add(i ,i - 1 ,-1);
           }
           spfa(Min ,Max);
           printf("%I64d
    " ,s_x[Max]);
        }
        return 0;
    }

  • 相关阅读:
    无线网路优化
    【设计模式】索引
    【c++算法】已序区间算法
    (转载)一个华为11年员工的国际惯例
    选择的结果
    明确价值体现
    只谈需求
    用block改写UIButton点击事件,block改写UIAlerView的代理
    UITableViewCell的三种加载方式
    如何从一个类的ViewController,如何获取一个UIView上的某种控件
  • 原文地址:https://www.cnblogs.com/csnd/p/12063051.html
Copyright © 2011-2022 走看看