题目链接:http://poj.org/problem?id=1364
题目大意:是否存在一个序列满足给的m组条件
si ni oi ki
如果oi=gt 表示:S(i+ni)-Si>ki
如果oi=lt 表示:S(i+ni)-Si<ki
由于查分约束的特点要变成x-y<=z的形势,因此对于上面的式子变形:
oi=gt ---> S(i+ni)-Si<=-ki-1
oi=lt ---> Si-S(i+ni)<=ki-1
然后建图,用spfa求最短路
代码如下:
#include<stdio.h>
#include<string.h>
#include<iostream>
using namespace std;
#define N 100000
#define M 100000
#define INF 999999999
int dis[N]; //记录距离
int vis[N]; //标记是否在队列中
int queue[N]; //模拟队列
int outqueue[N]; //记录点i出队的次数
int head[N];
int index, n; //index记录head[] s:源点 n个点
struct Edge
{
int v, next, value;
}edge[M];
void add_Edge(int u, int v, int val)
{
edge[index].next=head[u];
edge[index].v=v;
edge[index].value=val;
head[u]=index++;
}
int Spfa(int s)
{
int iq=0, front=0, i, top;
memset(vis, 0, sizeof(vis));
memset(outqueue, 0, sizeof(outqueue));
for(i=0; i<=n; i++)
dis[i]=INF;
dis[s]=0;
queue[iq++]=s;
vis[s]=1;
while(iq!=front)
{
top=queue[front];
front++;
vis[top]=0;
outqueue[top]++;
if(outqueue[top]>n) return 0;
for(i=head[top]; i!=-1; i=edge[i].next)
{
if(dis[top]+edge[i].value<dis[edge[i].v])
{
dis[edge[i].v]=dis[top]+edge[i].value;
if(vis[edge[i].v]==0)
{
vis[edge[i].v]=1;
queue[iq++]=edge[i].v;
}
}
}
}
return 1;
}
int main()
{
int si, ki, i, ni, m;
char ch[5];
while(scanf("%d", &n), n)
{
scanf("%d", &m);
index=0;
memset(head, -1, sizeof(head));
for(i=0; i<m; i++)
{
scanf("%d %d %s %d", &si, &ni, ch, &ki);
if(ch[0]=='g')
add_Edge(ni+si, si-1, -ki-1);
else
add_Edge(si-1, ni+si, ki-1);
}
for(i=1; i<=n; ++i) //i=0开始一直wa...wa死我了...泪奔TT...
add_Edge(n+1, i, 0);
if(Spfa(n+1))
printf("lamentable kingdom
");
else
printf("successful conspiracy
");
}
return 0;
}