King(差分约束)

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、超级源点的另一种建法     

 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 }
View Code

 其实Bellman_ford 比SPFA更快点,普通的Bellman_ford,记得要松弛 n次。

 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 }
View Code

 



posted on 2013-11-26 20:02  straw_berry  阅读(306)  评论(0编辑  收藏  举报