题意:给出一个数列S,对其中的一些段进行限制(规定了一段内所有数字加和的上界或下界),求是否存在这样的数列S满足所有限制。
分析:差分约束系统,
对于一组类似于xa-xb>=c的不等式求是否有满足的解,用bellman来解,bellman是使得dist[v] <= dist[u] + c。
差分约束是使得A-B>=C即 B<=A+(-C)。所以对于每个这样的不等式我们就从A向B连一条边边的权值为-C。
观察是否有负权回路,没有则有解,有则无解。求得的最短路即为最小解。
用sum[i]表示前i项和,限制了区段a+1~b的上界或下界为k,可以看成是sum[b]-sum[a]大于或小于k(大于等于k+1或者小于等于k-1)。即sum[a] <= sum[b] + (-k - 1)或者sum[b] <= sum[a] + (k - 1)。
这样就转化成了差分约束系统。

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
usingnamespace std;
#define maxn 105
#define inf 0x3f3f3f3f
int n, m, pre[maxn], edge[maxn][3];
int dist[maxn];
int relax(int u, int v, int c)
{
if (dist[v] > dist[u] + c)
{
dist[v] = dist[u] + c;
pre[v] = u;
return1;
}
return0;
}
int bellman(int src)
{
int i, j;
for (i =0; i < n; ++i)
{
dist[i] = inf;
pre[i] =-1;
}
dist[src] =0;
bool flag;
for (i =1; i < n; ++i)
{
flag =false;
for (j =0; j < m; ++j)
{
if (1== relax(edge[j][0], edge[j][1], edge[j][2]))
flag =true;
}
if (!flag)
break;
}
for (j =0; j < m; ++j)
{
if (1== relax(edge[j][0], edge[j][1], edge[j][2]))
return0;
}
return1;
}
void input()
{
char st[5];
for (int i =0; i < m; i++)
{
int a, b, c;
scanf("%d%d%s%d", &a, &b, st, &c);
if (st[0] =='g')
{
edge[i][0] = a + b;
edge[i][1] = a -1;
edge[i][2] =-c -1;
}
if (st[0] =='l')
{
edge[i][0] = a -1;
edge[i][1] = a + b;
edge[i][2] = c -1;
}
}
}
int main()
{
//freopen("t.txt", "r", stdin);
while (scanf("%d", &n), n)
{
n++;
scanf("%d", &m);
input();
if (bellman(0))
printf("lamentable kingdom\n");
else
printf("successful conspiracy\n");
}
return0;
}
#include <cstdio>
#include <cstdlib>
#include <cstring>
usingnamespace std;
#define maxn 105
#define inf 0x3f3f3f3f
int n, m, pre[maxn], edge[maxn][3];
int dist[maxn];
int relax(int u, int v, int c)
{
if (dist[v] > dist[u] + c)
{
dist[v] = dist[u] + c;
pre[v] = u;
return1;
}
return0;
}
int bellman(int src)
{
int i, j;
for (i =0; i < n; ++i)
{
dist[i] = inf;
pre[i] =-1;
}
dist[src] =0;
bool flag;
for (i =1; i < n; ++i)
{
flag =false;
for (j =0; j < m; ++j)
{
if (1== relax(edge[j][0], edge[j][1], edge[j][2]))
flag =true;
}
if (!flag)
break;
}
for (j =0; j < m; ++j)
{
if (1== relax(edge[j][0], edge[j][1], edge[j][2]))
return0;
}
return1;
}
void input()
{
char st[5];
for (int i =0; i < m; i++)
{
int a, b, c;
scanf("%d%d%s%d", &a, &b, st, &c);
if (st[0] =='g')
{
edge[i][0] = a + b;
edge[i][1] = a -1;
edge[i][2] =-c -1;
}
if (st[0] =='l')
{
edge[i][0] = a -1;
edge[i][1] = a + b;
edge[i][2] = c -1;
}
}
}
int main()
{
//freopen("t.txt", "r", stdin);
while (scanf("%d", &n), n)
{
n++;
scanf("%d", &m);
input();
if (bellman(0))
printf("lamentable kingdom\n");
else
printf("successful conspiracy\n");
}
return0;
}