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 }

 

posted on 2013-09-03 15:36  rootial  阅读(188)  评论(0编辑  收藏  举报

导航