差分约束,题目的关键在于建模的过程,这题题意比较难懂,数据各种BT,以前在HDU上过的,到UVA就不能过。

题目大意:
给定一个序列的长度,然后给定若干关系,这个关系是子序列各个元素之和与某个给定整数的大小关系。要求是否存在这样一个序列满足所有给定的若干关系。

 
思路:

本题主要就是需要想到利用前n个元素的和为替代。即设s[i] = a[1] + a[2] + …a[i]。
a[si] + a[si+1] + … + a[si + ni] = s[si + ni] - s[si - 1];所以如果a[si] + a[si+1] + … + a[si + ni] < k 则 s[si + ni] - s[si - 1] < k <= k - 1;如果a[si] + a[si+1] + … + a[si + ni] > k 则 s[si - 1] - s[si + ni] < -k <= -k - 1;

由于只要判断是否存在,而不考虑连通性的问题,我们可以加上一个超级源点n+1使得图连通,然后再判断序列时候存在即可(无正负环)。

另外,我以前的判环有错误,现在纠正过来吧~

CODE:

 

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <queue>
using namespace std;

#define MAXN 110
#define INF 0x3f3f3f3f
struct Edge
{
    int u, v, w;
    int next;
}edge[MAXN*5];

int d[MAXN], first[MAXN];
int n, m, cnt;

void init()
{
    cnt = 0;
    memset(first, -1sizeof(first));
}

void read_graph(int u, int v, int w)
{
    edge[cnt].v = v, edge[cnt].w = w;
    edge[cnt].next = first[u], first[u] = cnt++;
}

int spfa(int src)
{
    queue<int> q;
    bool inq[MAXN] = {0};
    int count[MAXN] = {0};
    for(int i = 0; i <= n+1; i++) d[i] = (i == src)?0:INF;
    q.push(src);
    while(!q.empty())
    {
        int x = q.front(); q.pop();
        inq[x] = 0;
        for(int e = first[x]; e != -1; e = edge[e].next)
        {
            int v = edge[e].v, w = edge[e].w;
            if(d[v] > d[x] + w)
            {
                d[v] = d[x] + w;
                //if(++count[v] >= n) 错误的判环
                if(!inq[v])
                {
                    inq[v] = 1;
                    if(++count[v] > n) return 0//判环在这里 
                    q.push(v);
                }
            }
        }
    }
    return 1;
}

int main()
{
    while(scanf("%d", &n) && n)
    {
        init();
        scanf("%d", &m);
        while(m--)
        {
            char str[3];
            int u, v, w;
            scanf("%d %d %s %d", &u, &v, &str, &w);
            if(str[0] == 'g')
            {
                read_graph(u+v, u-1, -w-1);
            }
            else
            {
                read_graph(u-1, u+v, w-1);
            }
        }
        int s = n+1;
        for(int i = 0; i <= n; i++) read_graph(i+1, i, INF/1000); //使得图连通,我以前是加一个超级源点使图连通,但WA。这里去网上参考了别人的代码该了下,这里我也不太懂。 
        if(spfa(s))
        {
            printf("lamentable kingdom\n");
        }
        else
        {
            printf("successful conspiracy\n");
        }
    }
    return 0;
}

 

 

posted on 2012-10-26 18:52  有间博客  阅读(272)  评论(0编辑  收藏  举报