差分约束,题目的关键在于建模的过程,这题题意比较难懂,数据各种BT,以前在HDU上过的,到UVA就不能过。
题目大意:
给定一个序列的长度,然后给定若干关系,这个关系是子序列各个元素之和与某个给定整数的大小关系。要求是否存在这样一个序列满足所有给定的若干关系。
思路:
本题主要就是需要想到利用前n个元素的和为替代。即设s[i] = a[1] + a[2] + …a[i]。
a[si] + a[si+1] + … + a[si + ni] = s[si + ni] - s[si - 1];所以如果a[si] + a[si+1] + … + a[si + ni] < k 则 s[si + ni] - s[si - 1] < k <= k - 1;如果a[si] + a[si+1] + … + a[si + ni] > k 则 s[si - 1] - s[si + ni] < -k <= -k - 1;
由于只要判断是否存在,而不考虑连通性的问题,我们可以加上一个超级源点n+1使得图连通,然后再判断序列时候存在即可(无正负环)。
另外,我以前的判环有错误,现在纠正过来吧~
CODE:
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <queue>
using namespace std;
#define MAXN 110
#define INF 0x3f3f3f3f
struct Edge
{
int u, v, w;
int next;
}edge[MAXN*5];
int d[MAXN], first[MAXN];
int n, m, cnt;
void init()
{
cnt = 0;
memset(first, -1, sizeof(first));
}
void read_graph(int u, int v, int w)
{
edge[cnt].v = v, edge[cnt].w = w;
edge[cnt].next = first[u], first[u] = cnt++;
}
int spfa(int src)
{
queue<int> q;
bool inq[MAXN] = {0};
int count[MAXN] = {0};
for(int i = 0; i <= n+1; i++) d[i] = (i == src)?0:INF;
q.push(src);
while(!q.empty())
{
int x = q.front(); q.pop();
inq[x] = 0;
for(int e = first[x]; e != -1; e = edge[e].next)
{
int v = edge[e].v, w = edge[e].w;
if(d[v] > d[x] + w)
{
d[v] = d[x] + w;
//if(++count[v] >= n) 错误的判环
if(!inq[v])
{
inq[v] = 1;
if(++count[v] > n) return 0; //判环在这里
q.push(v);
}
}
}
}
return 1;
}
int main()
{
while(scanf("%d", &n) && n)
{
init();
scanf("%d", &m);
while(m--)
{
char str[3];
int u, v, w;
scanf("%d %d %s %d", &u, &v, &str, &w);
if(str[0] == 'g')
{
read_graph(u+v, u-1, -w-1);
}
else
{
read_graph(u-1, u+v, w-1);
}
}
int s = n+1;
for(int i = 0; i <= n; i++) read_graph(i+1, i, INF/1000); //使得图连通,我以前是加一个超级源点使图连通,但WA。这里去网上参考了别人的代码该了下,这里我也不太懂。
if(spfa(s))
{
printf("lamentable kingdom\n");
}
else
{
printf("successful conspiracy\n");
}
}
return 0;
}
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <queue>
using namespace std;
#define MAXN 110
#define INF 0x3f3f3f3f
struct Edge
{
int u, v, w;
int next;
}edge[MAXN*5];
int d[MAXN], first[MAXN];
int n, m, cnt;
void init()
{
cnt = 0;
memset(first, -1, sizeof(first));
}
void read_graph(int u, int v, int w)
{
edge[cnt].v = v, edge[cnt].w = w;
edge[cnt].next = first[u], first[u] = cnt++;
}
int spfa(int src)
{
queue<int> q;
bool inq[MAXN] = {0};
int count[MAXN] = {0};
for(int i = 0; i <= n+1; i++) d[i] = (i == src)?0:INF;
q.push(src);
while(!q.empty())
{
int x = q.front(); q.pop();
inq[x] = 0;
for(int e = first[x]; e != -1; e = edge[e].next)
{
int v = edge[e].v, w = edge[e].w;
if(d[v] > d[x] + w)
{
d[v] = d[x] + w;
//if(++count[v] >= n) 错误的判环
if(!inq[v])
{
inq[v] = 1;
if(++count[v] > n) return 0; //判环在这里
q.push(v);
}
}
}
}
return 1;
}
int main()
{
while(scanf("%d", &n) && n)
{
init();
scanf("%d", &m);
while(m--)
{
char str[3];
int u, v, w;
scanf("%d %d %s %d", &u, &v, &str, &w);
if(str[0] == 'g')
{
read_graph(u+v, u-1, -w-1);
}
else
{
read_graph(u-1, u+v, w-1);
}
}
int s = n+1;
for(int i = 0; i <= n; i++) read_graph(i+1, i, INF/1000); //使得图连通,我以前是加一个超级源点使图连通,但WA。这里去网上参考了别人的代码该了下,这里我也不太懂。
if(spfa(s))
{
printf("lamentable kingdom\n");
}
else
{
printf("successful conspiracy\n");
}
}
return 0;
}