题意:考虑一个长度为n的序列是否存在,其中序列为S={a1,a2,a3,a4...ai...an},现在给出m个不等式,需要满足ai+a(i+1)+a(i+2)+...+a(i+n)<ki或者是ai+a(i+1)+a(i+2)+...+a(i+n)>ki。不等式如下描述:四个参数,其中第一个数i代表序列从第几项开始,第二个数n表示i后面有n个数(也即序列长为n+1,从a(i)...a(i+n)),第三个参数表示大于或者小于,第四个是数值。当符号为gt代表‘>’,符号为lt代表‘<'。样例意思为:
1 2 gt 0
a1+a2+a3>0
2 2 lt 2
a2+a3+a4<2
S3-S0>0---->S0-S3<=-1,
S4-S1<2---->S4-S1<=1。
因为差分约束的条件是小于等于,所以我们将小于号右边的数值-1可以将题意的小于变成小于等于。那么通式可以表示为
a b gt c
S[a-1]-s[a+b]<=-ki-1
a b lt c
S[a+b]-S[a-1]<=ki-1
接下来根据差分约束建图,加入这些有向边
gt: <a+b,a-1>=-ki-1
lt: <a-1,a+b>=ki-1
再根据spfa(或者bellman_ford)判断是否有无负环即可,若出现负环了则这个序列不满足所有的不等式。
1 2 gt 0
a1+a2+a3>0
2 2 lt 2
a2+a3+a4<2
最后问满足所有不等式的序列是否存在,若满足输出lamentable kingdom,不满足输出successful conspiracy。
S3-S0>0---->S0-S3<=-1,
S4-S1<2---->S4-S1<=1。
因为差分约束的条件是小于等于,所以我们将小于号右边的数值-1可以将题意的小于变成小于等于。那么通式可以表示为
a b gt c
S[a-1]-s[a+b]<=-ki-1
a b lt c
S[a+b]-S[a-1]<=ki-1
接下来根据差分约束建图,加入这些有向边
gt: <a+b,a-1>=-ki-1
lt: <a-1,a+b>=ki-1
再根据spfa(或者bellman_ford)判断是否有无负环即可,若出现负环了则这个序列不满足所有的不等式。
需要注意1、用spfa判断负环的时候要加入一个新节点,其与所有节点连边,权值为0。此题中新节点不能够用节点0,因为0节点在之前建图中可能已经用到(a和b虽然从1开始,但是建图时有插入a-1的可能)。所以新节点要用n+1号。2、spfa判断负环是在num数组值加一之后,不是放在队列为空之后统一判断,因为如果有负环队列可能根本就出不来。
#include <stdio.h>
#include <string.h>
#define INF 0x3fffffff
#define N 115
struct edge{
int y,next,w;
}e[1000];
int n,m;
char op[5];
int num[N],first[N],dis[N],top,q[100000];
void add(int x,int y,int w){
e[top].y = y;
e[top].w = w;
e[top].next = first[x];
first[x] = top++;
}
int relax(int x,int y,int w){
if(dis[x] + w < dis[y]){
dis[y] = dis[x] + w;
return 1;
}
return 0;
}
int spfa(){
int i,now,used[N],front,rear;
memset(used,0,sizeof(used));
memset(num,0,sizeof(num));
used[n+1] = 1;
dis[n+1] = 0;
for(i = 0;i<=n;i++)
dis[i] = INF;
front = rear = -1;
q[++rear] = n+1;
while(front < rear){
now = q[++front];
used[now] = 0;
for(i = first[now];i!=-1;i=e[i].next)
if(relax(now,e[i].y,e[i].w) && !used[e[i].y]){
q[++rear] = e[i].y;
used[e[i].y] = 1;
num [e[i].y]++;
if(num[e[i].y] > n)
return 0;
}
}
return 1;
}
int main(){
freopen("a.txt","r",stdin);
while(scanf("%d",&n) && n){
int i,a,b,c;
top=0;
memset(first,-1,sizeof(first));
scanf("%d",&m);
for(i = 0;i<m;i++){
scanf("%d %d %s %d",&a,&b,op,&c);
if(!strcmp(op,"gt"))
add(a+b,a-1,-c-1);
else
add(a-1,a+b,c-1);
}
for(i = 1;i<=n;i++)
add(n+1,i,0);
if(spfa())
printf("lamentable kingdom\n");
else
printf("successful conspiracy\n");
}
return 0;
}