链接:http://poj.org/problem?id=1364
题意:好吧,过了好几天才来写这个解题报告,我去。题意没忘,但是可能有点说不清了。不说了。。。
说一下学到的方法吧。
一、如果一个图可能不连通,则在运用SPFA时,先将所有的顶点入栈。这样做的目的是相当于虚设了一个源点,
该源点与所有的顶点连通(以便于检查是否存在负环)。而要注意的地方是,这个源点只是虚设的,若原先有N个
顶点,则在运用SPFA松弛(即把一个点的入栈)的次数要小于等于N-1次(也就是不包括虚设源点在内的)。
二、差分约束系统只适用于Xj-Xi<=w的情况,即是不等式!且必须要有等号!
如果遇到等式a-b=w,则可以变形为a-b>=w和a-b<=w,再来运用差分约束;
如果遇到等式a-b<w,就如这道题,要根据题意进行变形。因为题中给的是整数,
所以必有等式a-b<=w-1,这样就有了等号!!!就可以运用差分约束啦。
差分约束的题一定要灵活的变形。
#include<cstdio>
#include<cstring>
#include<queue>
#define MAXN 1005
#define MAXE 40000
using namespace std;
struct EDGE
{
int to,w;
int next;
}edge[MAXE];
int head[MAXN],dist[MAXN],vist[MAXN],inqu[MAXN];
int cnt;
void add(int u,int v,int w)
{
edge[cnt].to=v;
edge[cnt].w=w;
edge[cnt].next=head[u];
head[u]=cnt++;
}
int SPFA(int n)
{
int i,k;
memset(dist,0,sizeof(dist));
memset(vist,0,sizeof(vist));
memset(inqu,0,sizeof(inqu));
queue<int> q;
for(i=0;i<=n;i++)//将所有顶点入栈,使图连通,相当于构造虚源点
q.push(i);
while(!q.empty())
{
k=q.front();
q.pop();
vist[k]=0;
for(i=head[k];i!=-1;i=edge[i].next)
{
if(dist[edge[i].to]>dist[k]+edge[i].w)
{
dist[edge[i].to]=dist[k]+edge[i].w;
if(!vist[edge[i].to])
{
vist[edge[i].to]=1;
q.push(edge[i].to);
inqu[edge[i].to]++;
if(inqu[edge[i].to]>n)//第一次加入不算在内,一共n+1个顶点,所以最多只能松弛n次
return 0;
}
}
}
}
return 1;
}
int main()
{
int n,m;
int i,s,t,k;
char op[5];
while(scanf("%d",&n)&&n)
{
scanf("%d",&m);
cnt=0;
memset(head,-1,sizeof(head));
for(i=1;i<=m;i++)
{
scanf("%d%d%s%d",&s,&t,op,&k);
//scanf("%d%d%s%d",&s,&n,op,&k);
//一开始是这样的,n变量重名了,好像不止第一次犯这样的错误了
if(op[0]=='g')
{
add(t+s,s-1,-k-1);
}
else
{
add(s-1,t+s,k-1);
}
}
//for(i=0;i<=n;i++)
//add(n+1,i,0);
if(SPFA(n))
printf("lamentable kingdom\n");
else
printf("successful conspiracy\n");
}
return 0;
}