每行一个 n, m. n个序列 m个约束
设t为这个序列
(1)s n gt k t[s+1] + t[s+2]+......+t[s+n] >k
(2)s n lt k t[s+1] + t[s+2]+......+t[s+n] <k
设S[i]=t[1]+t[2]+t[3]+.....+t[i]
则(1):S[s+n] -S[s-1]>k -> S[s-1] -S[S+n] <-k
(2):S[s+n]-S[s-1]<k
因为差分约束 是u-v<=k 小于号只需要 变成 u-v<=k-1。
建立超级源,spfa算法能退出就说明有解,否则无解。可以把每个dist值都设置为0,然后加入到队列中,这样就省去了建立源点添边的功夫。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <vector>
#include <queue>
#define MAX_N 110
using namespace std;
struct edge{
int to,w;
};
int n,m;
char choice[2][3]={"gt","lt"};
int vis[MAX_N];
bool inque[MAX_N];
int dist[MAX_N];
vector<edge> g[MAX_N];
void init_graph()
{
for(int i=0;i<MAX_N;++i)
{
g[i].clear();
}
}
void add_edge(int u,int v,int w)
{
g[u].push_back((edge){v,w});
}
void add_constraint(int s,int t,char *str,int k)
{
if(!strcmp(str,choice[0]))// S[s+t]-S[s-1]>k -> S[s-1]-S[s+t]<-k
add_edge(s+t,s-1,-k-1);
else add_edge(s-1,s+t,k-1);//S[s+t]-S[s-1]<k
}
bool spfa()
{
memset(dist,0,sizeof(dist));
memset(vis,0,sizeof(vis));
memset(inque,0,sizeof(inque));
queue<int> que;
for(int i=0;i<=n;++i)
{
que.push(i);
inque[i]=1;
}
while(!que.empty())
{
int u=que.front();que.pop();
inque[u]=0;
++vis[u];
if(vis[u]>n) return false;
for(int i=0;i<g[u].size();++i)
{
edge &e=g[u][i];
if(dist[e.to]>dist[u]+e.w)
{
dist[e.to]=dist[u]+e.w;
if(!inque[e.to])
{
que.push(e.to);
inque[e.to]=1;
}
}
}
}
return true;
}
int main()
{
while(~scanf("%d",&n))
{
if(n==0)
break;
scanf("%d",&m);
int s,t,k;
char str[3];
init_graph();
for(int i=0;i<m;++i)
{
scanf("%d %d %s %d",&s,&t,&str,&k);
add_constraint(s,t,str,k);
}
bool ans=spfa();
if(ans)
printf("lamentable kingdom\n");
else printf("successful conspiracy\n");
}
return 0;
}