ZOJ1260/POJ1364国王(King)

// 题意 问是否存在一个长度为n的序列
// 这个序列满足m个限制
// 每个限制有 si ni oi ki
si 为序列位置 ni为从si开始连续长度为ni+1 的子序列 这些子序列和 大于或小于 ki 大于或小于要看oi了
// 令 s[i]表示 前 i个数字和 那么
// s[si+ni]-s[si-1]>k 或 <k 然后就出现差分约束了 然后 就可以了 外加一个点作为起点 到各点距离为0
// 这种分析好题目后就直接模板套上的题目就是做起来快

#include <iostream> #include <map> #include <algorithm> #include <queue> #include <math.h> #include <stdio.h> #include <string.h> #include <vector> using namespace std; #define MOD 1000000007 #define maxn 5010 #define maxm 510 struct node{ int to; int next; int val; }E[maxn]; int num; int V[maxm]; int d[maxm],cnt[maxm]; bool f[maxm]; bool sfpa(int s,int t){// s既表示起点 有表示节点个数 queue <int> Q; int u,v; int e; Q.push(s); d[s]=0; f[s]=true; while(!Q.empty()){ u=Q.front(); Q.pop(); cnt[u]++; if(cnt[u]>s) return false; f[u]=false; for(e=V[u];e!=-1;e=E[e].next){ v=E[e].to; if(d[u]+E[e].val<d[v]){ d[v]=d[u]+E[e].val; if(!f[v]) { f[v]=true; Q.push(v); } } } } return true; } int main(){ int i,j,k; int n,m; char str[6]; while(scanf("%d",&n),n){ scanf("%d",&m); for(i=0;i<=n+1;i++)// 开始这里写 i<=n 然后就一直超时、、郁闷 怎么就忘了我这有 n+2个点 { V[i]=-1; d[i]=MOD; cnt[i]=0; f[i]=false; } num=0; while(m--){ scanf("%d %d %s %d",&i,&j,str,&k); if(strcmp(str,"gt")==0){ E[num].to=i-1; E[num].val=-k-1; E[num].next=V[i+j]; V[i+j]=num++; } else { E[num].to=i+j; E[num].val=k-1; E[num].next=V[i-1]; V[i-1]=num++; } } for(i=0;i<=n;i++){ E[num].to=i; E[num].val=0; E[num].next=V[n+1]; V[n+1]=num++; } if(sfpa(n+1,0)) printf("lamentable kingdom\n"); else printf("successful conspiracy\n"); } }

 

你可能感兴趣的:(poj)