做简单转换,直接套用差分约束系统的模板即。
注意点:和Si(i=0,1,2,...,n)映射为Vi+1,增设源结点0,所以共有n+2个结点,需进行n+1次的松弛操作,其他的很简单。
#include <iostream>
#include <cstdio>
#include <cstring>
#define inf 10000000
using namespace std;
const int maxn=102;
int n,m,num,dist[maxn]; //各个顶点到源点的最短距离
struct Edge
{
int s;
int t;
int w;
}edge[4*maxn];
bool Bellman_Ford()
{
int i,j;
dist[0]=0;
for(i=0;i<=n;i++) //共有n+2个结点,增设的标号为0的结点,Si,i=0,1,2...n
for(j=0;j<num;j++) //Si映射为结点Vi+1,所以增设的结点是0,其他结点编号
if(dist[edge[j].s]+edge[j].w<dist[edge[j].t]) //为1-n+1,所以要进行n+1次松弛操作
dist[edge[j].t]=dist[edge[j].s]+edge[j].w;
for(i=0;i<num;i++)
if(dist[edge[i].s]+edge[i].w<dist[edge[i].t])
return false;
return true;
}
int main()
{
int i,si,ni,ki;
char oi[3];
while(scanf("%d",&n) && n!=0)
{
scanf("%d",&m);
num=0;
for(i=0;i<=n;i++) //源点的下标设为0,增设由源点指向其余各结点的有向边
{
edge[num].s=0;
edge[num].t=i+1;
edge[num++].w=0;
}
for(i=0;i<m;i++) //建图
{
scanf("%d%d%s%d",&si,&ni,oi,&ki);
if(strcmp(oi,"gt")==0) //oi=="gt"
{
edge[num].s=si+ni+1;
edge[num].t=si;
edge[num++].w=-ki-1;
}
else
{
edge[num].s=si;
edge[num].t=si+ni+1;
edge[num++].w=ki-1;
}
}
for(i=0;i<=n+1;i++)
dist[i]=inf;
if(Bellman_Ford())
printf("lamentable kingdom\n");
else
printf("successful conspiracy\n");
}
return 0;
}