zoukankan      html  css  js  c++  java
  • POJ 1364[差分约束]

    题目链接:【http://poj.org/problem?id=1364】

    晕死了。但是也长知识了

    题意:一个长度为n的序列:a[1]、a[2]、a[3]...a[n],然后给你一些约束条件:si、ni、gt||lt、ki表示:a[si]、a[si+1]、、、、a[si+ni]<or>ki,问你满足这些约束条件,字符串是否存在。存在输出:lamentable kingdom,否则输出:successful conspiracy

    题解:对序列求前缀和,将约束条件改为:sum[si+ni]-sum[si-1]<or>ki,为了方便:我们使其小标从1开始:sum[si+ni+1]-sum[si]<or>ki;

    但是:虽然我们可以根据上面的约束关系建立图,但是并不能保证图的联通,也就是说我们不一定能找到负环,我们可以对所有的点在加入一个相同的约束关系(这样做并不会影响最终的约束关系,但但是增加了图的连通性),添加约束关系的时候我们有两种方案:

    1、建立超级点,这个超级点1和任意一个点的约束关系都一样。

    2、在用SPFA求负环的时候,把所有的点加入队列并把dis[]初始化为零,(相当于建立了一个超级起点),然后判断是否有点入队的的次数大于N即可;

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    const int maxn = 150;
    int N, M;
    int u, v, d;
    char s[15];
    struct Edge
    {
        int id, next, len;
        Edge(int id = 0, int next = 0, int len = 0): id(id), next(next), len(len) {}
    } E[maxn];
    int head[maxn], tot;
    void init()
    {
        memset(head, -1, sizeof(head));
        tot = 0;
    }
    void adde(int u, int v, int len)
    {
        E[tot] = Edge{v, head[u], len};
        head[u] = tot++;
    }
    int top, stk[maxn], num[maxn];
    int dis[maxn], vis[maxn];
    bool SPFA(int st, int N)
    {
        for(int i = 0; i <= N; i++)
            dis[i] = 0, vis[i] = 1, num[i] = 0;;
        for(int i = 0; i < N; i++)
            stk[i] = i + 1;
        top = N + 1;
        while(top)
        {
            int u = stk[--top];
            vis[u] = 0;
            for(int k = head[u]; ~k; k = E[k].next)
            {
                int v = E[k].id;
                if(dis[v] > dis[u] + E[k].len)
                {
                    dis[v] = dis[u] + E[k].len;
                    if(vis[v]) continue;
                    vis[v] = 1;
                    stk[top++] = v;
                    num[v]++;
                    if(num[v] > N) return false;
                }
            }
        }
        return true;
    }
    int main ()
    {
        while(scanf("%d", &N), N)
        {
            init();
            scanf("%d", &M);
            for(int i = 1; i <= M; i++)
            {
                scanf("%d %d %s %d", &u, &v, s, &d);
                if(s[0] == 'l')
                    adde(u, u + v + 1, d - 1);//保证下标从1开始
                else
                    adde(u + v + 1, u, -d - 1);//变成 " <= ";
            }
            bool ans = SPFA(1, N + 1);
            if(!ans) printf("successful conspiracy
    ");
            else    printf("lamentable kingdom
    ");
        }
        return 0;
    }
    想的太多,做的太少。
  • 相关阅读:
    AGC007题解
    博弈论学习笔记
    ZROI2019 提高十连测
    男人八题2019
    LOJ 2840「JOISC 2018 Day 4」糖
    CF671D Roads in Yusland
    网络流套路小结
    BZOJ 3729 GTY的游戏
    AGC036C GP 2
    BZOJ 5046 分糖果游戏
  • 原文地址:https://www.cnblogs.com/pealicx/p/6719061.html
Copyright © 2011-2022 走看看