POJ 2983
POJ 2983 又是一条给我贡献wa率的题目。
问题大意:有一些点在同一直线上,给出他们之间的距离的关系(要么指定比他在北边多少,要么只告诉你在他北边(至少远1单位),求这些关系是否成立。
解:一开始觉得是差分约束,但是不想写bellman-ford,所以写了一坨if流,结果wa掉,看题解,写差分(用spfa),wa,wa,wa,wa,然后去orz _gxxd的程序,也没搞懂什么。最后得知判断条件是dist[u]+cost>dist[dest] then更改dist[dest]的值符合条件。然后关键点是如果是指定了远多少的边,一定要建立一条逆边,以便检查dist[u]+cost==dist[dest](因为有dist[dest]-cost=dist[u],所以同原来的判断条件,这个处理非常巧妙,不知道为什么写成不等式不行,还有就是试试写bellman-ford版)。另外的,用spfa的话要么初始化全部点都在队列里,要么构建一个超级源,这个点到其他1~n个点的距离都设置为0,这样就可以解决关于联通性的问题了。
View Code
1 const
2 maxn=1111*2;
3 maxm=111111*2;
4 bilibili=maxlongint >> 1;
5 type
6 data=record
7 dest, cost, next: longint;
8 end;
9 var
10 edge: array[1..maxm]of data;
11 key, q, dist, vect, low, dfn, col, s: array[1..maxn]of longint;
12 visit: array[1..maxn]of boolean;
13 ee, tot, color, time, stot, n, m: longint;
14 flag: boolean;
15
16 procedure print;
17 begin
18 if not flag then writeln('Unreliable')
19 else writeln('Reliable');
20 end;
21
22 procedure add(x, y, z: longint);
23 begin
24 inc(tot);
25 with edge[tot] do begin
26 dest := y;
27 cost := z;
28 next := vect[x];
29 vect[x] := tot;
30 end;
31 end;
32
33 procedure init;
34 var
35 i, j, x, y, z: longint;
36 c: char;
37 begin
38 tot := 0; stot := 0; time := 0; color := 0;
39 fillchar(vect, sizeof(vect), 0);
40 fillchar(visit, sizeof(visit), 0);
41 fillchar(col, sizeof(col), 0);
42 fillchar(dfn, sizeof(dfn), 0);
43 readln(n, m);
44 for i := 1 to m do begin
45 z := 1;
46 read(c);
47 if c='P' then begin readln(x, y, z); add(y, x, -z); end
48 else readln(x, y); // deal with
49 add(x, y, z);
50 end;
51 end;
52
53 procedure spfa(st: longint);
54 var
55 i, u, head, tail: longint;
56 begin
57 fillchar(visit, sizeof(visit), true);
58 fillchar(key, sizeof(key), 0);
59 head := 0; tail := n;
60 repeat
61 inc(head); if head=maxn+1 then head := 1;
62 u := q[head]; visit[u] := false;
63 inc(key[u]);
64 if key[u]>=n then begin
65 flag := false;
66 exit;
67 end;
68 i := vect[u];
69 while i<>0 do
70 with edge[i] do begin
71 if dist[u] + cost > dist[dest] then begin
72 dist[dest] := dist[u] + cost;
73 if not visit[dest] then begin
74 inc(tail); if tail=maxn +1 then tail := 1;
75 q[tail] := dest;
76 visit[dest] := true;
77 end;
78 end;
79 i := next;
80 end;
81 until head=tail;
82 end;
83
84 procedure main;
85 var
86 i, j: longint;
87 begin
88 flag := true;
89 fillchar(dist, sizeof(dist), 0);
90 for i := 1 to n do q[i] := i;
91 spfa(1);
92 end;
93
94
95 begin
96 assign(input,'1.txt'); reset(input);
97 while not(seekeof) do begin
98 init;
99 main;
100 print;
101 end;
102 end.