POJ 1273
POJ 1273 (吧?)
题目大意:就是混蛋网络流,不能再裸了。
解:请看文件夹内的关于网络流的理解。
by me of 2012.2.9
被网上的资料虐得一塌糊涂,有的甚至还是错的,看了三天终于切出来一条裸题了。
对于网络流,增广流的的不断贪心已经理解,但是在看标号法ford-fulkerson的时候,对于站在u点,对于点i,若边f[i, u]存在则视为逆向弧并处理这个不甚理解。
在整理自己理解的思路的时候,需要引入dinic的思想,不断通流导致全部通往sink汇点的路堵塞,算法结束,这里dinic每找到一条路得时候,在c[i, j] + flow的同时会连上一条边 c[j, i] - flow,这个是为了让流到这个点的流量给予反悔的机会,就是我先流到你了,随后发现你可以由其他流供应,我则不必再继续供应此点了。
对于图
2 1
1 -> 2 -> 3
1| | 2 | 1
V V V
4 -> 5 -> 6
1 2
可以发现,如果不连回去的边,若因图顺序的特殊性,我们先增广了 1, 2, 5, 6,则会发现没有路走了,最大流=2,但显然答案是3
所以关于dinic的性质总结完毕,关于ford-fulkerson,对于负边的检查我们也可以用这个图来理解,
在增广了1, 2, 5, 6, 后,我们走 1, 4, 5, 2, 3, 6,完成对此图的增广,对于5到6的跳跃,可以理解为,点5已经有流,所以2->5算逆向弧,我们看看能不能返还流给点2,然后看看2能不能给其他路这些多余的流,自然,我们要保证退还的等于从4给予过来的因此flow = min(l[i], fij)
对于
: 正向弧 : l[j] = min(l[i], cij - fij)
逆向弧 : l[j] = min(l[i], fij)
我们也能理解了吧?
yoshi,去看dinic
1 const
2 maxn=211;
3 maxm=211;
4 var
5 f, g: array[1..maxn, 1..maxn]of longint;
6 q, last, now: array[1..maxn]of longint;
7 visit: array[1..maxn]of boolean;
8 head, tail, flow, s, t, ans, n, m: longint;
9 procedure init;
10 var
11 x, y, z, i, j: longint;
12 begin
13 fillchar(f, sizeof(f), 0);
14 fillchar(g, sizeof(g), 0);
15 ans := 0;
16 readln(m, n);
17 for i := 1 to m do
18 begin
19 readln(x, y, z);
20 g[x, y] := g[x, y] + z;
21 end;
22 end;
23
24 function check: longint;
25 var
26 i: longint;
27 begin
28 for i := 1 to n do
29 if (last[i]<>0)and(not visit[i]) then exit(i);
30 exit(0);
31 end;
32
33 function ford: boolean;
34 var
35 u, i, j, k, x: longint;
36 begin
37 ford := true;
38 fillchar(last, sizeof(last), 0);
39 fillchar(visit, sizeof(visit), 0);
40 last[s] := s;
41 head := 0;
42 tail := 1;
43 repeat
44 u := check;
45 if u=0 then exit(true);
46 for i := 1 to n do
47 if (last[i]=0)and((g[u, i]<>0)or(g[i, u]>0)) then
48 begin
49 if g[u, i]>f[u, i] then last[i] := u;
50 if f[i, u]>0 then last[i] := -u;
51 end;
52 visit[u] := true;
53 until last[t]<>0;
54 i := t; flow := maxlongint;
55 repeat
56 j := i;
57 i := abs(last[i]);
58 if last[j]<0 then x := f[j, i];
59 if last[j]>0 then x := g[i, j] - f[i, j];
60 if flow > x then flow := x;
61 until i = 1;
62 exit(false);
63 end;
64
65 procedure fulkerson(flow: longint);
66 var
67 i, j: longint;
68 begin
69 i := t;
70 repeat
71 j := i; i := abs(last[i]);
72 if last[j]<0 then f[j, i] := f[j, i] - flow;
73 if last[j]>0 then f[i, j] := f[i, j] + flow;
74 until i=s;
75 end;
76
77 procedure main;
78 var
79 flag : boolean;
80 begin
81 s := 1;
82 t := n;
83 flow := 0;
84 repeat
85 flag := ford;
86 if flag then exit
87 else fulkerson(flow);
88 until false;
89 end;
90
91 procedure print;
92 var
93 i: longint;
94 begin
95 for i := 2 to n do
96 if f[1, i]<>0 then ans := ans + f[1, i];
97 writeln(ans);
98 end;
99
100 begin
101 assign(input,'ditch.in'); reset(input);
102 assign(output,'ditch.out'); rewrite(output);
103 while not eof do
104 begin
105 init;
106 main;
107 print;
108 end;
109 close(input);
110 end.