zoukankan      html  css  js  c++  java
  • Intervals---poj1201(差分约束系统)

    题目链接:http://poj.org/problem?id=1201

    题目说[ai, bi]区间内和点集Z至少有ci个共同元素,那也就是说如果我用Si表示区间[0,i]区间内至少有多少个元素的话,那么Sbi - Sai >= ci,这样我们就构造出来了一系列边,权值为ci,但是这远远不够,因为有很多点依然没有相连接起来(也就是从起点可能根本就还没有到终点的路线),此时,我们再看看Si的定义,也不难写出0<=Si - Si-1<=1的限制条件,虽然看上去是没有什么意义的条件,但是如果你也把它构造出一系列的边的话,这样从起点到终点的最短路也就顺理成章的出现了。

    我们将上面的限制条件写为同意的形式:

    Sbi - Sai >= ci

    Si - Si-1 >= 0

    Si-1 - Si >= -1

    因为要求的是最小有多少个,所以要求最长路;

    所以求出图中最小点到最大点的最大距离即可;

    #include <iostream>
    #include <stdio.h>
    #include <math.h>
    #include <string.h>
    #include <queue>
    #include <stack>
    #include <algorithm>
    #include <map>
    #include <string>
    typedef long long LL;
    #define INF 0x3f3f3f3f
    #define met(a, b) memset(a, b, sizeof(a))
    #define N 51500
    
    using namespace std;
    
    int S, E, vis[N], dist[N];
    struct node
    {
        int u, v, w, Next;
    }e[N*3];
    
    int Head[N], cnt;
    
    void Add(int u, int v, int w)
    {
        e[cnt].v = v;
        e[cnt].w = w;
        e[cnt].Next = Head[u];
        Head[u] = cnt++;
    }
    
    int spfa()
    {
        for(int i=0; i<=E; i++)
            dist[i] = -INF;
        met(vis, 0);
        queue<int> Q;
        Q.push(S);
        vis[S] = 1;
        dist[S] = 0;
        while(!Q.empty())
        {
            int p = Q.front();Q.pop();
            vis[p] = 0;
            for(int i=Head[p]; i!=-1; i=e[i].Next)
            {
                int q = e[i].v;
                if(dist[q] < dist[p]+e[i].w)///最长路;
                {
                    dist[q] = dist[p]+e[i].w;
                    if(!vis[q])
                    {
                        vis[q] = 1;
                        Q.push(q);
                    }
                }
            }
        }
        return dist[E];
    }
    
    int main()
    {
        int n, u, v, w;
        while(scanf("%d", &n) != EOF)
        {
            met(e, 0);
            met(Head, -1);
            cnt = 0;
            S = INF; E = -INF;///找到对应的起点和终点;
            for(int i=1; i<=n; i++)
            {
                scanf("%d %d %d", &u, &v, &w);
                Add(u, v+1, w);///u可能等于0,所以v+1比较好;
                S = min(u, S);
                E = max(v+1, E);
            }
            for(int i=S; i<E; i++)///建立其他边,所以e要开3倍的N;
            {
                Add(i, i+1, 0);
                Add(i+1, i, -1);
            }
            int ans = spfa();
            printf("%d
    ", ans);
        }
        return 0;
    }
    View Code
  • 相关阅读:
    Git使用
    A star算法
    禅语人生
    android中GridView
    关于Android资源学习
    买了胡百敬老师的<SQL SERVER 2008 管理实战>
    人生七苦
    SQL Server 2008实现"编辑所有行"和"返回所有行"的方法
    陈慧娴《永远是你的朋友》专辑歌词
    SQL Server 2008 Service Pack 1 简体中文补丁包下载
  • 原文地址:https://www.cnblogs.com/zhengguiping--9876/p/5813907.html
Copyright © 2011-2022 走看看