zoukankan      html  css  js  c++  java
  • 杭电oj1384--Intervals(差分约束)

    题目:http://acm.hdu.edu.cn/showproblem.php?pid=1384

    题意:  N 表示有几组测试数据, a , b, c -- >[a, b] 表示一个闭区间, c 表示闭区间内符合条件的点数。 求满组符合N个条件所需最少的点。

    这种题主要是找约束方程。

    约束方程有两个:(不得不吐个槽, 真nm不好想),设 s[i] 为0 ~ i在集合Z中满足点的个数, 集合Z为最终所求集合;

     1、在集合[a, b]中, s[a+1] - s[b] >= c . (注意集合长度、 这里要用最长路解决问题----->注意建边方向)。

     2、1 >= s[i+1] - s[i] >= 0; (这条件不太明显,Nm-.-). 转化一下---> s[i] >= s[i-1] - 1 && s[i + 1] >= 0 + s[i]方向!!!) yuan point = imPoRtant.

    #include <queue>
    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #define min(a, b) a<b? a:b
    #define max(a, b) a>b? a:b
    using namespace std;
    const int INF = 0x3f3f3f3f;
    int dis[50010], vis[50010], Min, Max;
    struct Edge
    {
        int from, to, val, next;
    } edge[50005*3];
    int head[50005], cnt;
    void Add(int a, int b, int c)
    {
        Edge E = {a, b, c, head[a]};
        edge[cnt] = E; 
        head[a] = cnt++;
    }
    void Spfa()
    {
        for(int i = Min; i <= Max; i++)
            dis[i] = -INF;
        dis[Min] = 0;            //最长路;
        queue<int> Q;
        Q.push(Min);
        while(!Q.empty())
        {
            int u = Q.front(); Q.pop();
            vis[u] = 0;
            for(int i = head[u]; i != -1; i = edge[i].next)
            {
                int v = edge[i].to;
                if(dis[v] < dis[u] + edge[i].val)
                {
                    dis[v] = dis[u] + edge[i].val;
                    if(!vis[v])
                    {
                        vis[v] = 1;
                        Q.push(v);
                    }
                }    
            }    
        } 
        printf("%d ", dis[Max]);
    }
    int main()
    {
        int N;
        while(~scanf("%d", &N))
        {
            Min = INF; Max = -INF;  cnt = 0;
            memset(vis, 0sizeof(vis));
            memset(edge, 0sizeof(edge));
            memset(head, -1sizeof(head));
            for(int i = 0; i < N; i++)
            {
                int u, v, w;
                scanf("%d %d %d", &u, &v, &w);
                Add(u, v+1, w);                  //s[a+1] - s[b] >= c ;
                Min = min(Min, u);               //找大致区间;
                Max = max(Max, v+1); 
            }
            for(int i = Min; i < Max; i++)
            {
                Add(i, i+10);                 //双向边, 权值不同。1 >= s[i+1] - s[i] >= 0---> s[i] >= s[i-1] - 1 && s[i + 1] >= 0 + s[i]
                Add(i+1, i, -1);    
            } 
            Spfa();
        }
        return 0; }


  • 相关阅读:
    大数据下高并发的处理详解
    【玩转TensorFlow】TensorFlow常见问题详解
    在阿里云上两分钟玩转AlextNet
    【前端精华】React源码分析系列
    svm
    神经网络结构选择
    神经网络反向传播跳出局部极小
    ubuntu16.04设置电池充电阈值
    pandas datafram重命名列名称
    centos6.8/ubuntu 安装python2.7 or python3.6
  • 原文地址:https://www.cnblogs.com/soTired/p/4779783.html
Copyright © 2011-2022 走看看