POJ 1364 King

POJ_1364

这个题目其实还算是比较简单的差分约束系统的题目。一开始其实已经把输入数据的约束条件都找全了,如果设S[i][a1,ai]的和,那么如果符号是gt,则有S[ai+ni]-S[ai-1]>=ki+1,如果符号是lt,则有S[ai-1]-S[ai+ni]>=-ki+1。然后发现这个图可能从S[n]开始做最短路不是连通的,于是我便想加两个辅助条件S[i]-S[i-1]>=-INFS[i]-S[i-1]<=INF,这两个条件是没有问题的,但可能是由于INF精度的问题而WA掉了。

后来再看了别人的报告之后,发现其实让图连通不用这么麻烦。首先,做最短路没必要把S[n]S[0]的最短路求出来,只要判断题目中的数据是否存在负圈就可以了,所以没必要把整个图都连通起来。如果用最短路判负圈的方法的话,可以抽象出一个点使其和其他点都连通就可以了,于是可以想象成a[n+1]是一个很大的点,这样可以保证S[n+1]+S[i]>=0,图就连通了。但如果都初始化d[]INF的话,那实际上d[n+1]d[i]之间有一条权值为0的路相当于是不连通的,因为求最短路的时候是过不去的,当然为了保证路是通的,可以把d[n+1]初始化的值弄得比INF小一点。或者不如干脆保证S[n+1]+S[i]>=-1,这样d[]就可以都初始化成INF了。这个a[n+1]也就是所谓的超级源点,由于这个点使我们自定义的,所以添加进去的不等式不会影响最后的结果。

此外,如果用SPFA来判断负圈的话,由于这个图实际上是有n+1个点,所以入队次数要大于n+1才可以判定存在负圈,如果大于n就判定有负圈的话会WA掉的。

#include<stdio.h>
#include
<string.h>
int first[110],next[210],v[210],w[210];
int q[11000],inq[110],inedq[110],d[110];
char b[5];
int main()
{
int i,j,si,ni,ki,m,n,u,ok,front,rear,temp,e;
while(1)
{
scanf(
"%d",&n);
if(n==0)
break;
scanf(
"%d",&m);
memset(first,
-1,sizeof(first));
for(e=0;e<m;e++)
{
scanf(
"%d%d%s%d",&si,&ni,b,&ki);
if(b[0]=='g')
{
v[e]
=si-1;
w[e]
=-ki-1;
next[e]
=first[si+ni];
first[si
+ni]=e;
}
else
{
v[e]
=si+ni;
w[e]
=ki-1;
next[e]
=first[si-1];
first[si
-1]=e;
}
}
for(i=0;i<=n+1;i++)
{
d[i]
=1000000000;
inq[i]
=inedq[i]=0;
}
for(i=0;i<=n;i++)
{
v[e]
=i;
w[e]
=-1;
next[e]
=first[n+1];
first[n
+1]=e;
e
++;
}
d[n
+1]=1000000000;
front
=rear=0;
q[rear
++]=n+1;
ok
=1;
while(front<rear)
{
u
=q[front++];
inq[u]
=0;
for(e=first[u];e!=-1;e=next[e])
if(d[u]+w[e]<d[v[e]])
{
d[v[e]]
=d[u]+w[e];
if(!inq[v[e]])
{
q[rear
++]=v[e];
inq[v[e]]
=1;
if(inedq[v[e]]++>n)
{
ok
=0;
front
=rear;
break;
}
}
}
}
if(ok)
printf(
"lamentable kingdom\n");
else
printf(
"successful conspiracy\n");
}
return 0;
}

  

你可能感兴趣的:(poj)