题目链接:http://poj.org/problem?id=1364
借鉴了一位的大佬的博客:
https://www.cnblogs.com/cchun/archive/2012/09/02/2667585.html
题目大意;
已知一个序列a[1], a[2], ……, a[n],给出它的若干子序列以及对该子序列的
约束条件,例如a[si], a[si+1], a[si+2], ……, a[si+ni],且a[si]+a[si+1]
+a[si+2]+……+a[si+ni] < or > ki。求是否存在满足以上m个要求的数列。是
则输出“lamentable kingdom”,否则输出“successful conspiracy”。
解题思路:
s[a] + s[a+1] + …… + s[b] < c 可以转化成前n项和sum[b] - sum[a - 1] < c,
为了能用Bellman_Ford,即将< 转化成 <= ,sum[b] - sum[a - 1] <= c - 1。
转化为最长路或者最短路来判断是否有解都可以。
代码:
#include <iostream>
#include <stdio.h>
#include <math.h>
#include <string.h>
#include <string>
#include <stdlib.h>
#include <algorithm>
#include <queue>
#include <vector>
using namespace std;
const int maxn =200+5;
const int inf =0x3f3f3f3f;
int head[maxn],vis[maxn],d[maxn],cnt[maxn],k;
int n,m;
queue<int> q;
void init()
{
k=0;
memset(head,-1,sizeof(head));
memset(vis,0,sizeof(vis));
memset(d,inf,sizeof(d));
memset(cnt,0,sizeof(cnt));
while(!q.empty())
q.pop();
}
struct Edge
{
int v,w,next;
Edge(){};
Edge(int v1,int w1,int next1)
{
v=v1,w=w1,next=next1;
}
}e[maxn*2];
void add_edge(int u, int v, int w)
{
e[k]=Edge(v,w,head[u]);
head[u]=k++;
}
int spfa()
{
d[n+1]=0;
vis[n+1]=1;
q.push(n+1);
cnt[n+1]++;
while(!q.empty())
{
int u=q.front();
q.pop();
vis[u]=0;
for(int i=head[u];i!=-1; i=e[i].next)
{
int v=e[i].v;
int w=e[i].w;
if(d[v]>d[u]+w)
{
d[v]=d[u]+w;
if(!vis[v])
{
q.push(v);
vis[v]=1;
cnt[v]++;
if(cnt[v]>n+2)
return 0;
}
}
}
}
return 1;
}
int main()
{
while(scanf("%d",&n)!=EOF&&n)
{
init();
scanf("%d",&m);
int a,b,c;
char s[10];
for(int i=0; i<m; i++)
{
scanf("%d %d %s %d",&a,&b,s,&c);
if(s[0]=='g')
{
add_edge(a+b,a-1,-(c+1));
}
else
{
add_edge(a-1,a+b,c-1);
}
}
for(int i=0; i<=n; i++)//如果选择0作为超级源点的话,d[0]可以一直变化,不恒为0
add_edge(n+1,i,0);
spfa() ?printf("lamentable kingdom\n"):printf("successful conspiracy\n");
}
return 0;
}