[差分约束]poj 1364:King

大致题意:
    告诉你有一列长度为n的数列和m个关系式。每个关系式的表述为:
    si ni “gt” c 或者是  si ni “lt” c。分别代表该数列第si项一直加到第si+ni项的和大于c,和第si项一直加到第si+ni项的和小于c。求是否存在满足以上m个要求的数列。是则输出“lamentable kingdom”,否则输出“successful conspiracy”。

 

大致思路:

    把问题转化为差分约束。将差分约束系统中的点sum[i]设为这个数列前i项的和。当要求第si项一直加到第si+ni项的和大于c的时候,就等价于sum[si+ni]-sum[si-1]>c,又由于差分约束系统中只能出现<=关系且这里的数字都是整数,所以上式又可以转化为sum[i-1]-sum[i+n]<=-c-1。

    对于“第si项一直加到第si+n项的和小于c”的要求,我们同样可以将其转化为sum[si+ni]-sum[si-1]<=c-1;

    按照得到的式子构出差分约束系统,用spfa判断是否存在可行解即可。

 

详细代码:

 

#include<iostream>
#include<cmath>
#include<cstdio>
#include<cstring>
using namespace std;
const int nMax=1050;
const int mMax=1000050;
const int inf=1<<28;
struct{
    int v, next;
    int  w;
}edge[mMax];
int n, k, head[nMax];
int dis[nMax],issea[nMax];
int stack[nMax],m,sum[nMax];
bool vis[nMax];

void addedge(int a,int b,int w){
    edge[k].w = w;
    edge[k].v=b;
    edge[k].next=head[a];
    head[a]=k;k++;
}

bool spfa(int s){
    int i, top = 0;
    memset(vis,0,sizeof(vis));
    for(i=0;i<=n;i++)dis[i]=inf;
    dis[s]=0;
    stack[++top]=s;
    vis[s]=true;
    while(top){
       // cout<<top<<endl;
        int u=stack[top--];
        for(i=head[u];i!=0;i=edge[i].next){
            int v=edge[i].v;
            if(dis[v]>dis[u]+edge[i].w){
                dis[v]=dis[u]+edge[i].w;
                if(!vis[v]){
                    vis[v]=true;
                    stack[++top] = v;
                    if(++sum[v]>n)return 0;
                  //  cout<<v<<" "<<sum[v]<<endl;;
                }
            }
        }
        vis[u]=false;
    }
    return 1;
}

int main(){
    int i,j,si,ni,c,s;
    char str[10];
    while(scanf("%d",&n)!=EOF&&n){
        scanf("%d",&m);
        k=1;
        s=n+2;      //s作为加入差分约束系统的“虚拟点”
        memset(head,0,sizeof(head));
        memset(sum,0,sizeof(sum));
        for(i=1;i<=n;i++){
            addedge(s,i,0);
        }
        while(m--){
            scanf("%d%d%s%d",&si,&ni,str,&c);
            if(str[0]=='g'){
                addedge(si+ni,si-1,-c-1);
            }
            else{
                addedge(si-1,si+ni,c-1);
            }
        }
        if(spfa(s)){
            printf("lamentable kingdom\n");
        }
        else{
            printf("successful conspiracy\n");
        }
    }
    return 0;
}

你可能感兴趣的:(差分约束,poj 1364,King)