http://poj.org/problem?id=1364 这题题目比较晦涩难懂,我是直接去看的网上的解释。是道差分约束的题,题目大意是这样:有一个序列S={a1,a2,a3,....,am},现在给出一些不等式
使得ai+a(i+1)+a(i+2)+.......+a(i+ni)>ki或者ai+a(i+1)+a(i+2)+.......+a(i+ni)<k。(注意这里是从ai本身开始后面再加ni个数),让你判断是否所有的不等式都满足条件,满足就输出
lamentable kingdom,不满足就输出successful conspiracy。(注意不要输反了,一开始我就是输反了 ,导致一直在查自己SPFA的错。。。)由于差分约束只能解决同时大于等于或者同时小于等于的情况,所以我们需要对题给不等式做一些变形。
1).形如 ai ni gt ki 这种形式的 表示ai+a(i+1)+a(i+2)+.......+a(i+ni)>ki ,我们令Si 表示序列前i项的和 ,则前面不等式等价于 :
S(i+ni)-S(i-1)>ki <=> S(i-1)-S(i+ni)<=-ki -1;
2). 对 ai ni lt ki 一样的道理,转化为S(i+ni)-S(i-1)<ki <=> S(i+ni)-S(i-1)<=ki-1;
这就是所有的通式,最后根据差分约束建立有向图:
gt: 建立有向边:(i+ni) -> (i-1) 权值为:-ki-1
lt :建立有向边: (i-1) -> (i+ni) 权值为:ki-1
最后判断是否所有不等式成立的条件就是是否有负环产生。直接用Bellman_ford或者spfa都行,接下来的就跟poj2983的处理一样了。下面是AC的代码:
再这里抱怨一句,不知道为什么,这题我用添加超源点的方式一直WA,改用下面这种方式才A了,但是把相同的添加源点的代码写到poj2983(http://blog.csdn.net/lyx35405/article/details/10053309)里面竟然能过。。
#include <cstdio>
#include <cstring>
#include <iostream>
#include <queue>
#include <algorithm>
using namespace std;
#define inf 999999999
#define maxn 1003*10
struct node
{
int y,w,next;
}edge[maxn];
queue<int> que;
int n,num,m;
int first[maxn],dis[maxn],fnum[maxn];
bool visit[maxn];
void initGraph(int x,int y,int w)
{
edge[++num].y=y;edge[num].w=w;
edge[num].next=first[x];
first[x]=num;//相当于链表的头插入法,顶点x的所有边为一个邻接表
}
bool SPFA()
{
memset(visit,1,sizeof(visit));
memset(fnum,0,sizeof(fnum));
memset(dis,0,sizeof(dis));
for(int i=0;i<=n;i++) que.push(i);
//visit[n+1]=1;
while(!que.empty())
{
int x=que.front();
que.pop();
visit[x]=0;
for(int i=first[x];i!=0;i=edge[i].next)
{
int y=edge[i].y;
if(dis[x]+edge[i].w<dis[y])
{
dis[y]=dis[x]+edge[i].w;
if(!visit[y])
{
visit[y]=1;
if(++fnum[y]>n) return 0;//无解
//printf("fnum[%d]=%d\n",y,fnum[y] );
que.push(y);
}
}
}
}
return 1 ;//有解
}
int main()
{
int si,ni,ki;
char op[5];
while(scanf("%d",&n)==1&&n)
{
scanf("%d",&m);
num=0;
memset(first,0,sizeof(first));
while(m--)
{
scanf("%d%d%s%d",&si,&ni,op,&ki);
if(op[0]=='g')
initGraph(si+ni,si-1,-ki-1);
else
initGraph(si-1,si+ni,ki-1);
}
if(!SPFA()) printf("successful conspiracy\n");
else printf("lamentable kingdom\n");
}
return 0;
}