zoukankan      html  css  js  c++  java
  • POJ-1201/HDU-1384 Intervals

    题目大意:

    有一个整数集合Z,现在给出n个整数区间[a,b]以及|Z∩[a,b]|的最少个数c,让你求这个整数集合的最小有多少

    解题思路:

    差分约束系统+spfa

    差分约束系统事实上就是一个构图的过程

    比如说现在有n个不等式

    X1 - X2 <= a

    X2 - X3 <= b

    ...

    X(n-1) - Xn <= ggg

    假如现在问你Xn - X1的最小值是多少,如何求解?

    首先这些式子必然会有两种情况,一种是必然没有解,一种是无数解

    对于有无数解的情况,必然是存在一种情况满足最小解,其实根据上面这些不等式很容易知道X1 - Xn <= a + b + ... + ggg那么答案就出来了。

    那么根据推广之后的式子该怎么解呢?

    首先根据这些式子构建有向图,但是这个有向图是可能存在重边,存在负权边的情况,那么只需要通过spfa算法计算从点1到点n的最小距离就解出来了。

    如果这个图存在负环的时候,就说明这个解不存在。

    差分约束就是这样的一种思想。

    代码:

    #include <queue>
    #include <cstdio>
    #include <vector>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    
    typedef struct node{
        int to, w;
        node(int a = 0, int b = 0){
            to = a; w = b;
        }
    }Edge;
    
    const int INF = 0x3f3f3f3f;
    const int maxn = 51000;
    
    vector<Edge> vec[maxn];
    int vis[maxn], dis[maxn];
    
    int spfa(int s, int e){
        int p, len; Edge nxt;
    
        queue<int> q;
        while(!q.empty()) q.pop();
        for(int i = 0; i <= e; ++i){
            vis[i] = 0;
            dis[i] = INF;
        }
    
        q.push(s); vis[s] = 1; dis[s] = 0;
        while(!q.empty()){
            p = q.front();
            q.pop();
    
            len = vec[p].size();
            for(int i = 0; i < len; ++i){
                nxt = vec[p][i];
                if(dis[p] + nxt.w < dis[nxt.to]){
                    dis[nxt.to] = dis[p] + nxt.w;
                    if(!vis[nxt.to]){
                        vis[nxt.to] = 1;
                        q.push(nxt.to);
                    }
                }
            }
            vis[p] = 0;
        }
        return -dis[e];
    }
    int main(){
        int n, a, b, c;
        while(~scanf("%d", &n)){
            int be = INF, en = 0;
            for(int i = 0; i < maxn; ++i) vec[i].clear();
            for(int i = 0; i < n; ++i){
                scanf("%d%d%d", &a, &b, &c);
                vec[a-1].push_back(Edge(b,-c));
                be = min(be, a);
                en = max(en, b);
            }
            for(int i = be - 1; i < en; ++i){
                vec[i].push_back(Edge(i+1, 0));
                vec[i+1].push_back(Edge(i, 1));
            }
            printf("%d
    ", spfa(be - 1, en));
        }
        return 0;
    }


  • 相关阅读:
    Codeforces 627A XOR Equation(思路)
    Codeforces 633C Spy Syndrome 2(DP + Trie树)
    BZOJ 1982 [Spoj 2021]Moving Pebbles(博弈论)
    BZOJ 3676 [Apio2014]回文串(回文树)
    BZOJ 3790 神奇项链(manacher+DP+树状数组)
    Codeforces 449D Jzzhu and Numbers(高维前缀和)
    SPOJ Time Limit Exceeded(高维前缀和)
    BZOJ 4031 [HEOI2015]小Z的房间(Matrix-Tree定理)
    BZOJ 3809 Gty的二逼妹子序列(莫队+分块)
    BZOJ 3544 [ONTAK2010]Creative Accounting(set)
  • 原文地址:https://www.cnblogs.com/wiklvrain/p/8179429.html
Copyright © 2011-2022 走看看