zoukankan      html  css  js  c++  java
  • UVA 515 King

    差分约束系统的第一个题目,看了落花大神的博客后,对差分约束有了一定了解,关键在于建图,然后就是判断是否存在负权回路。

    关于差分约束系统的解释详见维基百科:http://zh.wikipedia.org/wiki/%E5%B7%AE%E5%88%86%E7%BA%A6%E6%9D%9F%E7%B3%BB%E7%BB%9F

    利用spfa判断时,当图中有顶点出队次数多于图中顶点数目时说明存在负环。

    其实我自己敲上去的时候改了一点点。

    大神的time[g[x][i].v]当达到n+1时就返回false,这是不对的,因为点包括0嘛,所以最终应该有n+1个点,判断就应该改为达到n+2,而且这一点也从uva上得到证明,

    直接交n+1的版本是过不了的,n+2,才能过。

    以下是我改过大神的代码:

     1 #include <cstdio>
     2 #include <cstring>
     3 #include <queue>
     4 #include <cstdlib>
     5 #include <vector>
     6 #define N 110
     7 using namespace std;
     8 
     9 struct edgeType{
    10 int v, w;
    11 edgeType(int a, int b):v(a), w(b){}
    12 };
    13 int n, m, d[N], time[N], inq[N];
    14 char op[10];
    15 
    16 vector<edgeType> g[N];
    17 bool spfa(void)
    18 {
    19     queue<int> q;
    20      time[n] = 1;
    21      inq[n] = 1;
    22      q.push(n);
    23      while(!q.empty())
    24      {
    25          int x = q.front();
    26          q.pop();
    27          inq[x] = 0;
    28          for(int i = 0; i < g[x].size(); i++)
    29             if(d[g[x][i].v] > d[x] + g[x][i].w)
    30          {
    31              d[g[x][i].v] = d[x] + g[x][i].w;
    32              time[g[x][i].v]++;
    33              if(time[g[x][i].v] == n+2)
    34                 return false;
    35              if(!inq[g[x][i].v])
    36              {
    37                  q.push(g[x][i].v);
    38                  inq[g[x][i].v] = 1;
    39              }
    40          }
    41      }
    42      return true;
    43 }
    44 
    45 int main(void)
    46 {
    47     int a, b, c;
    48     while(scanf("%d%d",&n, &m)&&n)
    49     {
    50         n++;
    51         memset(d, 0x0f, sizeof(d));
    52         memset(inq, 0, sizeof(inq));
    53         memset(time, 0, sizeof(time));
    54         d[n] = 0;
    55         g[n].clear();
    56         for(int i = 0; i < n;i++)
    57             g[n].push_back(edgeType(i, 0)), g[i].clear();
    58         for(int i = 0; i < m; i++)
    59         {
    60             scanf("%d%d%s%d", &a, &b, op, &c);
    61             if(op[0] == 'g')
    62                 g[a + b].push_back(edgeType(a - 1, -c - 1));
    63             else g[a - 1].push_back(edgeType(a + b, c - 1));
    64         }
    65         if(spfa())
    66             puts("lamentable kingdom");
    67         else puts("successful conspiracy");
    68     }
    69     return 0;
    70 }

    然后我利用bellman—ford重新写了一遍,速度慢了将近一半,不知道是不是我写的姿势不对。

    来自维基百科的bellman-ford的伪代码:

    # initialization
    for each v in V do 
        d[v] ← ∞; 
    d[source] ← 0
    # Relaxation
    for i =1,...,|V|-1 do
        for each edge (u,v) in E do
            d[v] ← min{d[v], d[u]+w(u,v)}
    # Negative cycle checking
    for each edge (u, v) in E do 
        if d[v]> d[u] + w(u,v) then 
            no solution

    其实就是普通bellman-ford做完之后,再检查所有的边一次,看看能不能继续松弛,如果可以的话,松弛变数会超过:|V|-1,说明必须存在负权环。

     1 #include <cstdio>
     2 #include <cstring>
     3 #include <queue>
     4 #include <cstdlib>
     5 #include <vector>
     6 #define N 110
     7 using namespace std;
     8 
     9 struct edgeType
    10 {
    11     int v, w;
    12     edgeType(int a, int b):v(a), w(b) {}
    13 };
    14 int n, m, d[N], inq[N];
    15 char op[10];
    16 vector<edgeType> g[N];
    17 
    18 bool bellman_ford(void)
    19 {
    20     for(int k = 0; k < n; k++)
    21         for(int x = 0; x <= n; x++)
    22             for(int i = 0; i < (int)g[x].size(); i++)
    23                 if(d[g[x][i].v] > d[x] + g[x][i].w)
    24                     d[g[x][i].v] = d[x] + g[x][i].w;
    25     for(int i = 0; i <= n; i++)
    26     {
    27         for(int k = 0; k < (int)g[i].size(); k++)
    28             if(d[g[i][k].v] > d[i] + g[i][k].w)
    29                 return false;
    30     }
    31     return true;
    32 }
    33 
    34 int main(void)
    35 {
    36     int a, b, c;
    37     while(scanf("%d",&n)&&n)
    38     {
    39         n++;
    40         scanf("%d", &m);
    41         memset(d, 0x0f, sizeof(d));
    42         memset(inq, 0, sizeof(inq));
    43         d[n] = 0;
    44         g[n].clear();
    45         for(int i = 0; i < n; i++)
    46             g[n].push_back(edgeType(i, 0)), g[i].clear();
    47         for(int i = 0; i < m; i++)
    48         {
    49             scanf("%d%d%s%d", &a, &b, op, &c);
    50             if(op[0] == 'g')
    51                 g[a + b].push_back(edgeType(a - 1, -c - 1));
    52             else g[a - 1].push_back(edgeType(a + b, c - 1));
    53         }
    54         if(bellman_ford())
    55             puts("lamentable kingdom");
    56         else puts("successful conspiracy");
    57     }
    58     return 0;
    59 }
  • 相关阅读:
    内存Fuzz和WinAFL
    AFL分析与实战
    协议Fuzz技术
    Fuzz技术综述与文件Fuzz
    WireShark学习笔记(一)
    虚拟机连接的问题
    jq 时间的代理和父级的删除
    Windows(WSL2) Linux子系统搭建Docker环境
    JavaCV FFmpeg H264编码
    JavaCV FFmpeg AAC编码
  • 原文地址:https://www.cnblogs.com/rootial/p/3298839.html
Copyright © 2011-2022 走看看