差分约束
题目大意:已知一个连续的数列a[i],给你这个数列的一些约束条件(如a[i]+a[i+1]+……+a[i+s]大于或小于k)以及这个数列的长度,问是否存在这样一个数列满足上述条件,若有则输出lamentable kingdom,否则输出successful conspiracy。
典型的差分约束,约束条件题目已经给定。由于只需判断是否有解,因此跑最长路或最短路都可以。注意符号即可。
最短路的约束条件:
a[si-1] - a[si+ni] <= - ki - 1
a[si+ni] - a[si-1] <= ki - 1
贴上代码(我因为spfa写错RE了好多次。。。。):
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
struct edge{
int next;
int to;
int dis;
};
int n,m,k;
int h[105],dis[505];
bool f[105];
bool flag;
edge a[100005];
char s1,s2;
void read(int x,int y,int z){
k++;
a[k].next=h[x];
a[k].to=y;
a[k].dis=z;
h[x]=k;
}
void spfa(){
memset(dis,0x7f,sizeof(dis));
memset(f,false,sizeof(f));
flag=false;
int b[100000]={0};
int r=0,w=1;
b[1]=0; f[0]=true;
dis[0]=0;
while (r<w){
int x=b[++r];
f[x]=false;
for (int i=h[x];i;i=a[i].next)
if (dis[a[i].to]>dis[x]+a[i].dis){
dis[a[i].to]=dis[x]+a[i].dis;
if (!f[a[i].to]){
b[++w]=a[i].to;
f[a[i].to]=true;
if (w>90000){
flag=true;
break;
}
}
}
if (flag)
break;
}
}
int main(){
while (scanf("%d",&n)&&n){
scanf("%d",&m);
memset(h,0,sizeof(h));
k=0;
for (int i=1;i<=m;i++){
int x,y,z;
scanf("%d %d %c%c %d",&x,&y,&s1,&s2,&z);
if (s1=='g')
read(x+y+1,x,-z-1);
else
read(x,x+y+1,z-1);
}
for (int i=1;i<=n+1;i++)
read(0,i,0);
spfa();
if (flag)
printf("successful conspiracy\n");
else
printf("lamentable kingdom\n");
}
return 0;
}