简介:
给出若干形如
a(si) + a(si+1) + … + a(si+ni) < ki
a(si) + a(si+1) + … + a(si+ni) > ki
的不等式,询问是否存在合法的a序列
分析:
柿子都是区间和的形式
这就在提醒我们把区间和变成前缀和的差
比如说不等式
a(si) + a(si+1) + … + a(si+ni) < ki
a(si) + a(si+1) + … + a(si+ni) > ki
我们可以转化为
sum(si+ni)-sum(si-1) <= ki-1
sum(si-1)-sum(si+ni) <= -ki-1
这样就完全符合差分约束的形式了
我们还是用Bellman判负环的方法求解就好了
tip
注意结点数目
在判断负环的时候,最规范的写法是
++cnt>(n+1)
因为一共有n+1个结点(0~n)
//这里写代码片
#include<cstdio>
#include<cstring>
#include<iostream>
#include<vector>
#include<algorithm>
#include<queue>
using namespace std;
const int N=203;
int n,m;
struct node{
int x,y,v;
};
struct Bellman{
int n,m;
vector<node> e;
vector<int> G[N];
bool in[N];
int cnt[N];
int dis[N];
int pre[N];
void init(int n)
{
this->n=n;
e.clear();
for (int i=0;i<=n;i++) G[i].clear();
}
void add(int u,int w,int z)
{
e.push_back((node){u,w,z});
m=e.size();
G[u].push_back(m-1);
}
bool fuhuan()
{
memset(in,0,sizeof(in));
memset(cnt,0,sizeof(cnt));
queue<int> Q;
for (int i=0;i<=n;i++)
{
in[i]=1; dis[i]=0;
Q.push(i);
}
while (!Q.empty())
{
int now=Q.front(); Q.pop();
in[now]=0;
for (int i=0;i<G[now].size();i++)
{
node way=e[G[now][i]];
if (dis[way.y]>dis[now]+way.v)
{
dis[way.y]=dis[now]+way.v;
pre[way.y]=G[now][i];
if (!in[way.y])
{
in[way.y]=1;
Q.push(way.y);
if (++cnt[way.y]>(n+1)) return 1;
}
}
}
}
return 0;
}
};
Bellman A;
int main()
{
while (scanf("%d%d",&n,&m)==2)
{
A.init(n);
char opt[5];
for (int i=1;i<=m;i++)
{
int u,w,z;
scanf("%d%d%s%d",&u,&w,&opt,&z);
w+=u,u--;
if (opt[0]=='g') //>
{
A.add(w,u,-z-1);
}
else
{
A.add(u,w,z-1);
}
}
if (A.fuhuan()) //无解
printf("successful conspiracy
");
else printf("lamentable kingdom
");
}
}