http://poj.org/problem?id=1364
题意真心看不大懂啊。。。
现在假设有一个这样的序列,S={a1,a2,a3,a4...ai...at}
其中ai=a*si,其实这句可以忽略不看
现在给出一个不等式,使得ai+a(i+1)+a(i+2)+...+a(i+n)<ki或者是ai+a(i+1)+a(i+2)+...+a(i+n)>ki
首先给出两个数分别代表S序列有多少个,有多少个不等式
不等式可以这样描述
给出四个参数第一个数i可以代表序列的第几项,然后给出n,这样前面两个数就可以描述为ai+a(i+1)+...a(i+n),即从i到n的连续和,再给出一个符号和一个ki
当符号为gt代表‘>’,符号为lt代表‘<'
那么样例可以表示
1 2 gt 0
a1+a2+a3>0
2 2 lt 2
a2+a3+a4<2
最后问你所有不等式是否都满足条件,若满足输出lamentable kingdom,不满足输出successful conspiracy,这里要注意了,不要搞反了
解题思路:一个典型的差分约束,很容易推出约束不等式
首先设Si=a1+a2+a3+...+ai
那么根据样例可以得出
S3-S0>0---->S0-S3<=-1
S4-S1<2---->S4-S1<=1
因为差分约束的条件是小于等于,所以我们将ki-1可以得到一个等于号
那么通式可以表示为
a b gt c
S[a-1]-s[a+b]<=-ki-1
a b lt c
S[a+b]-S[a-1]<=ki-1
那么根据差分约束建图,加入这些有向边
gt: <a+b,a-1>=-ki-1
lt: <a-1,a+b>=ki-1
再根据bellman_ford 或 SPAF 判断是否有无负环即可
若出现负环了则这个序列不满足所有的不等式
继续SPFA吧。。
这里用了无需建立超级源点的SPFA算法,在SPFA开始时将所有结点都放进队列,这样表示一开始和所有点都相连了,初始化dis数组为全0,相当于超级源点的边权值
总结:1、小于和小于等于关系的转化 2、超级源点的另一种建法
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 #include<stdio.h> 2 #include<string.h> 3 #include<queue> 4 using namespace std; 5 const int maxn = 110; 6 7 int n,m; 8 int cnt; 9 int p[maxn]; 10 struct node 11 { 12 int u,v,w; 13 int next; 14 }edge[maxn]; 15 16 void add(int u, int v, int w) 17 { 18 cnt++; 19 edge[cnt].u = u; 20 edge[cnt].v = v; 21 edge[cnt].w = w; 22 edge[cnt].next = p[u]; 23 p[u] = cnt; 24 } 25 //无需建立超级源点的SPFA 26 int SPFA() 27 { 28 queue<int> que; 29 while(!que.empty()) 30 que.pop(); 31 int dis[maxn],vexcnt[maxn]; 32 bool inque[maxn]; 33 memset(dis,0,sizeof(dis));//dis全部初始化为0, 34 memset(inque,true,sizeof(inque));//inque全部初始化为1 35 memset(vexcnt,0,sizeof(vexcnt)); 36 37 for(int i = 0; i <= n; i++) 38 que.push(i);//先让所有节点进队列 39 while(!que.empty()) 40 { 41 int u = que.front(); 42 que.pop(); 43 inque[u] = false; 44 45 for(int i = p[u]; i; i = edge[i].next) 46 { 47 if(dis[edge[i].v] > dis[u] + edge[i].w) 48 { 49 dis[edge[i].v] = dis[u] + edge[i].w; 50 if(!inque[edge[i].v]) 51 { 52 inque[edge[i].v] = true; 53 que.push(edge[i].v); 54 vexcnt[edge[i].v]++; 55 if(vexcnt[edge[i].v] > n)//进队超过n次说明有负环 56 return 0; 57 } 58 } 59 } 60 } 61 return 1; 62 } 63 64 int main() 65 { 66 while(~scanf("%d",&n) && n) 67 { 68 scanf("%d",&m); 69 int a,b,w; 70 char str[5]; 71 cnt = 0; 72 memset(p,0,sizeof(p)); 73 for(int i = 0; i < m; i++) 74 { 75 scanf("%d %d %s %d",&a,&b,str,&w); 76 if(strcmp(str,"gt") == 0) 77 add(a+b,a-1,-w-1);//加边 78 else add(a-1,a+b,w-1);//加边,均将不等式转化为 <=, 79 } 80 if(SPFA()) printf("lamentable kingdom\n"); 81 else printf("successful conspiracy\n"); 82 83 } 84 return 0; 85 }
其实Bellman_ford 比SPFA更快点,普通的Bellman_ford,记得要松弛 n次。
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 #include<stdio.h> 2 #include<string.h> 3 #include<queue> 4 using namespace std; 5 const int maxn = 110; 6 7 int n,m; 8 int cnt; 9 struct node 10 { 11 int u,v,w; 12 }edge[maxn]; 13 14 void add(int u, int v, int w) 15 { 16 edge[cnt].u = u; 17 edge[cnt].v = v; 18 edge[cnt].w = w; 19 cnt++; 20 } 21 int bellman_ford() 22 { 23 int dis[maxn]; 24 memset(dis,0,sizeof(dis)); 25 26 for(int i = 1; i <= n; i++) 27 { 28 for(int j = 0; j < m; j++) 29 { 30 if(dis[edge[j].v] > dis[edge[j].u] + edge[j].w) 31 dis[edge[j].v] = dis[edge[j].u] + edge[j].w; 32 } 33 } 34 for(int j = 0; j < m; j++) 35 { 36 if(dis[edge[j].v] > dis[edge[j].u] + edge[j].w) 37 return 0; 38 } 39 return 1; 40 } 41 int main() 42 { 43 while(~scanf("%d",&n) && n) 44 { 45 scanf("%d",&m); 46 int a,b,w; 47 char str[5]; 48 cnt = 0; 49 for(int i = 0; i < m; i++) 50 { 51 scanf("%d %d %s %d",&a,&b,str,&w); 52 if(strcmp(str,"gt") == 0) 53 add(a+b,a-1,-w-1);//加边 54 else add(a-1,a+b,w-1);//加边,均将不等式转化为 <=, 55 } 56 if(bellman_ford()) 57 printf("lamentable kingdom\n"); 58 else printf("successful conspiracy\n"); 59 } 60 return 0; 61 }