POJ 1364 King (差分约束系统)

题目描述有点复杂,前面讲了一大堆废话。

题目大意:对一个含n个整数的序列进行一些约束:

1、整数序列中连续的一段的和大于某个整数;

2、整数序列中连续的一段的和小于某个整数。

问满足以上约束的整数序列是否存在。

分析:首先利用前缀和进行转换,然后将>化为>=,将<化为<=,然后就基本是裸的差分约束系统了。

需要注意的是,建立的约束图可能并不是无向连通的,所以需要另外加一个结点作为源点,由于加了一个点,所以判断是否有负环时要注意,条件是某个点进队次数大于n+1

View Code
#include <stdio.h>
#include <string.h>
#include <queue>
using namespace std;
#define N 110
#define M 210
#define INF 0x3fffffff
int n,m;
int d[N];
int inq[N],cnt[N];
int first[N],v[M],next[M],w[M];
int e;
void init()
{
    e=0;
    memset(first,-1,sizeof(first));
}
void insert(int a,int b,int c)
{
    v[e]=b;
    w[e]=c;
    next[e]=first[a];
    first[a]=e++;
}
void spfa()
{
    queue<int> q;
    int a,b;
    bool loop=false;

    memset(inq,0,sizeof(int)*(n+5));
    memset(cnt,0,sizeof(int)*(n+5));

    for(int i=0;i<=n;i++)   d[i]=INF;
    d[n+1]=0;
    inq[n+1]=1;
    q.push(n+1);
    cnt[n+1]++;
    while(!q.empty())
    {
        a=q.front(),q.pop();
        if(cnt[a]>n+1)   { loop=true;    break; }
        inq[a]=0;
        for(int i=first[a];i!=-1;i=next[i])
        {
            b=v[i];
            if(d[b]>d[a]+w[i])
            {
                d[b]=d[a]+w[i];
                if(inq[b]==0)   inq[b]=1,q.push(b),cnt[b]++;
            }
        }
    }
    if(loop)    puts("successful conspiracy");
    else   puts("lamentable kingdom");
}
int main()
{
    int i;
    int a,b,c;
    char s[5];
    while(scanf("%d",&n),n)
    {
        init();
        scanf("%d",&m);
        for(i=0;i<m;i++)
        {
            scanf("%d%d%s%d",&a,&b,s,&c);
            if(s[0]=='g')
            {
                insert(a+b,a-1,-c-1);
            }
            else
            {
                insert(a-1,a+b,c-1);
            }
        }
        for(i=0;i<=n;i++) insert(n+1,i,0);
        spfa();
    }
    return 0;
}
posted @ 2012-07-24 17:34  BeatLJ  阅读(203)  评论(0编辑  收藏  举报