题目描述有点复杂,前面讲了一大堆废话。
题目大意:对一个含n个整数的序列进行一些约束:
1、整数序列中连续的一段的和大于某个整数;
2、整数序列中连续的一段的和小于某个整数。
问满足以上约束的整数序列是否存在。
分析:首先利用前缀和进行转换,然后将>化为>=,将<化为<=,然后就基本是裸的差分约束系统了。
需要注意的是,建立的约束图可能并不是无向连通的,所以需要另外加一个结点作为源点,由于加了一个点,所以判断是否有负环时要注意,条件是某个点进队次数大于n+1
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#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; }