zoukankan      html  css  js  c++  java
  • 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
    ");
    81         else printf("successful conspiracy
    ");
    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
    ");
    58         else printf("successful conspiracy
    ");
    59     }
    60     return 0;
    61 }
    View Code



  • 相关阅读:
    Java对象序列化/反序列化的注意事项
    初尝Java序列化/反序列化对象
    Java的byte数组
    在C#或者SWT上跨进程访问SWT控件的问题
    Enum实现单例模式
    看个泛型的例子
    构造器优化需要多个构造器的类(建造者模式)
    线程间操作无效: 从不是创建控件的线程访问它.
    SWT中的多线程(Invalid thread access)
    读书笔记 --腾讯传
  • 原文地址:https://www.cnblogs.com/LK1994/p/3444023.html
Copyright © 2011-2022 走看看