zoukankan      html  css  js  c++  java
  • 【题解】ZOJ1420 Cashier Employment

      论文——冯威《浅析差分约束系统》。

      论文讲得很详细,就不解释了。主要想记录一下对于差分约束的理解(感觉以前的学习真的是在囫囵吞枣啊……)

      差分约束系统,同于解决线性的不等关系是否存在合法解 & 求得最大 / 最小解。当其中牵涉到的式子形如 (A[i] - A[i - 1] >= (<=) x) 时,就可以运用差分约束求解了。处理的方法是由于这个式子为三角形不等式,即spfa中的松弛操作,所以我们看做一个图论的问题,跑最长路 最短路即可。连边的方式自己画图感知就好了。

      当需要求解最大 / 最小值时:最大值运用最短路,最小值运用最长路。以求最大值为例:一个数能够取得的最大值即在满足了最小的约束情况下可以取得的最大值,而道路边权即为约束边,所以为最短路。

      通用解法:1.罗列出不等关系(注意要找全了)。2.移项,未知数一边,常数一边。3.考虑运用最长路 / 最短路求解。这题主要在于构建出方程与函数来描述不等关系的特征,当常数中有未知项时,可以考虑枚举求解(其实这个思想很重要,数据范围小的时候一定考虑枚举暴力呀)。当然这题由于满足单调性,所以二分一下~

    #include <bits/stdc++.h>
    using namespace std;
    #define maxn 300000
    int cnp = 1, head[maxn], num[maxn];
    int R[maxn], dis[maxn], in[maxn];
    bool vis[maxn];
    
    struct edge
    {
        int to, last, co;
    }E[maxn];
    
    int read()
    {
        int x = 0, k = 1;
        char c;
        c = getchar();
        while(c < '0' || c > '9') { if(c == '-') k = -1; c = getchar(); }
        while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
        return x * k;
    }
    
    void add(int u, int v, int w)
    {
        E[cnp].to = v, E[cnp].co = w;
        E[cnp].last = head[u], head[u] = cnp ++;
    }
    
    bool spfa()
    {
        queue <int> q;
        for(int i = 1; i <= 30; i ++)
            dis[i] = -99999999;
        memset(vis, 0, sizeof(vis));
        memset(in, 0, sizeof(in));
        dis[0] = 0, q.push(0);
        while(!q.empty())
        {
            int u = q.front(); q.pop();
            vis[u] = 0;
            for(int i = head[u]; i; i = E[i].last)
            {
                int v = E[i].to;
                if(dis[v] < dis[u] + E[i].co)
                {
                    dis[v] = dis[u] + E[i].co;
                    if(!vis[v])
                    {
                        if(++ in[v] == 26) return 1;
                        vis[v] = 1; q.push(v);
                    } 
                }
            }
        }
        return 0;
    }
    
    void Build(int mid)
    {
        memset(head, 0, sizeof(head)); cnp = 1;
        for(int i = 1; i <= 24; i ++)
        {
            add(i - 1, i, 0);
            add(i, i - 1, -num[i]);
        }
        for(int i = 8; i <= 24; i ++)
            add(i - 8, i, R[i]);
        for(int i = 1; i < 8; i ++)
            add(i + 16, i, R[i] - mid);
        add(0, 24, mid); 
    }
    
    int main()
    {
        int T = read();
        while(T --)
        {
            for(int i = 1; i <= 24; i ++) R[i] = read();
            int n = read();
            memset(num, 0, sizeof(num));
            for(int i = 1; i <= n; i ++)
            {
                int x = read();
                num[x + 1] ++;
            }
            Build(n);
            if(spfa())
            { 
                printf("No Solution
    ");
                continue;
            }
            int l = 0, r = n, ans;
            while(l <= r)
            {
                int mid = (l + r) >> 1;
                Build(mid);
                if(spfa()) l = mid + 1;
                else ans = mid, r = mid - 1;
            }
            printf("%d
    ", ans);
        }
        return 0;
    }
  • 相关阅读:
    JavaEE——SpringMVC(11)--拦截器
    JavaEE——SpringMVC(10)--文件上传 CommonsMultipartResovler
    codeforces 460A Vasya and Socks 解题报告
    hdu 1541 Stars 解题报告
    hdu 1166 敌兵布阵 解题报告
    poj 2771 Guardian of Decency 解题报告
    hdu 1514 Free Candies 解题报告
    poj 3020 Antenna Placement 解题报告
    BestCoder5 1001 Poor Hanamichi(hdu 4956) 解题报告
    poj 1325 Machine Schedule 解题报告
  • 原文地址:https://www.cnblogs.com/twilight-sx/p/9180853.html
Copyright © 2011-2022 走看看