poj1364

题意:给出一个数列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)。

这样就转化成了差分约束系统。

View Code
#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;
}
原文地址:https://www.cnblogs.com/rainydays/p/2088043.html