题目大意:
有一个序列S={a1 ,a2 ........an}, 现在告诉你许多区间从第i个元素到第i+n个元素的和的范围是大于K或者小于K,问你这些条件是否能够同时满足。
解题思路:
这是我所做的第一道差分约束的题目,以前看差分约束的时候看到那张矩阵连乘的图就不想看下去了(线代学的不好)
后来才知道与那个没什么毛线关系啊,其实就是给出m个关于n个元素的关系式,然后求解吗。。。。求解的方法是构造出不等式组(高中学过吧。。。。)然后求解,其实这个可以用最短路来求哦。。。。
就拿这道题来说吧,不等式组是。。。
假设Si=a1+a2+...ai
{
s(i+n) - s(i-1)<K
s(i+n) - s(i-1)>K
}
==>
{
s(i+n)-s(i-1)<=k-1;
s(i-1)-s(i+n)<=-k-1;
}
......然后构造图。。。
链式前向星。。。。。。。
#include<stdio.h>
#include<queue>
using namespace std;
const int N = 109;
int n,m;
struct node{
int to;
int dis;
int next;
};
int head[N],h;
node edg[N];
void add(int a,int b,int d)
{
edg[h].to=b;
edg[h].dis=d;
edg[h].next=head[a];
head[a]=h;
h++;
}
bool in_q[N];
int cnt[N],dis[N];
queue<int>q;
int spfa()
{
int cur,k,v;
while(!q.empty())
{
cur=q.front();
q.pop();
in_q[cur]=false;
for(k=head[cur];k!=-1;k=edg[k].next)
{
v=edg[k].to;
if(dis[v]>dis[cur]+edg[k].dis)
{
dis[v]=dis[cur]+edg[k].dis;
if(!in_q[v])
{
q.push(v);
in_q[v]==true;
cnt[v]++;
if(cnt[v]>n)
return 0;//需要清空队列的真正原因。。。。
}
}
}
}
return 1;
}
void init()
{
int i;
for(i=0;i<=n;i++)
{
head[i]=-1;
dis[i]=0;//既然只要判断其是否有负环的话。。。
in_q[i]=false;
cnt[i]=0;
}
h=0;
while(!q.empty())//忘了讲队列清空了,我去。。。。
q.pop();
}
int main()
{
char buf[10];
int i,u,v,d;
while(scanf("%d",&n)&&n)
{
scanf("%d",&m);
init();
for(i=0;i<m;i++)
{
scanf("%d%d%s %d",&u,&v,buf,&d);
if(buf[0]=='g'){
add(u+v,u-1,-d-1);
q.push(u+v);
}
else{
add(u-1,u+v,d-1);
q.push(u-1);
}
}
if(spfa())
puts("lamentable kingdom");
else
puts("successful conspiracy");
}
}