每行一个 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; }