POJ 3422

POJ 3422

题目大意:原题的加强版,k取方格数。

解:dp,dp+降维,因为这里k可以到10,用最大费用流做。先拆点,一个点变成两个点,点中间有两条边,一条费用为该方格数,流量为1,(其负边的费用是负,一开始没想到wa了好久),另一条边费用为0而流量为无限。每次找一条去到汇点的最大费用路。然后找出最小流,用pre记录前缀,从汇点回溯到原点,并更新每条边的流量。注意原点到1,1的流量为maxlongint,n,n到汇点的流量为k。这里也是wa的地方。

View Code
  1 //poj 3422
2 const
3 maxn=(52 * 52) << 1;
4 maxm=(maxn << 2)+ 10086;
5 bilibili=maxlongint >> 1;
6 type
7 data=record
8 dest, next, cost, w, op: longint;
9 end;
10 var
11 edge: array[1..maxm]of data;
12 q, vect, dist, from, from_edge: array[1..maxn]of longint;
13 visit: array[1..maxn]of boolean;
14 flow, ans, tot, sink, source, n, k: longint;
15 procedure add(x, y, z, fy: longint);
16 begin
17 inc(tot);
18 with edge[tot] do begin
19 dest := y;
20 cost := z;
21 w := fy;
22 next := vect[x];
23 vect[x] := tot;
24 op := tot +1;
25 end;
26 inc(tot);
27 with edge[tot] do begin
28 dest := x;
29 cost := 0;
30 w := -fy;
31 next := vect[y];
32 vect[y] := tot;
33 op := tot -1;
34 end;
35 end;
36
37 procedure init;
38 var
39 i, j, x, tmp, y, z: longint;
40 begin
41 tot := 0; ans := 0;
42 fillchar(vect, sizeof(vect), 0);
43 readln(n, k);
44 source := (n*n)<<1 +1; sink := source +1;
45 for i := 1 to n do begin
46 for j := 1 to n do begin
47 read(tmp);
48 x := (i-1)*n + j;
49 y := x << 1;
50 x := y-1;
51 add(x, y, 1, tmp);
52 add(x, y, bilibili, 0);
53 x := y;
54 y := ((i-1)*n+j+1)<<1 -1;
55 z := (i*n+j)<<1 -1;
56 if j<n then add(x, y, bilibili, 0);
57 if i<n then add(x, z, bilibili, 0);
58 end;
59 readln;
60 end;
61 add(source, 1, bilibili, 0);
62 add(n*n*2, sink, k, 0);
63 end;
64
65 function spfa: boolean;
66 var
67 head, tail, i, u: longint;
68 begin
69 for i := 1 to sink do dist[i] := -bilibili;
70 fillchar(visit, sizeof(visit), 0);
71 head := 0; tail := 1;
72 q[tail] := source; dist[source] := 0;
73 visit[source] := true;
74 repeat
75 inc(head); if head=maxn+1 then head := 1;
76 u := q[head];
77 visit[u] := false;
78 i := vect[u];
79 while i<>0 do
80 with edge[i] do begin
81 if (cost>0)and(dist[u] + w > dist[dest]) then begin
82 dist[dest] := dist[u] +w;
83 from[dest] := u;
84 from_edge[dest] := i;
85 if not visit[dest] then begin
86 inc(tail); if tail=maxn + 1 then tail := 1;
87 visit[dest] := true;
88 q[tail] := dest;
89 end;
90 end;
91 i := next;
92 end;
93 until head=tail;
94 exit(dist[sink]<>-bilibili);
95 end;
96
97 procedure main;
98 var
99 i, u: longint;
100 begin
101 while spfa do begin
102 u := sink;
103 flow := bilibili;
104 while u<>source do begin
105 if edge[from_edge[u]].cost < flow then flow := edge[from_edge[u]].cost;
106 u := from[u];
107 end;
108 u := sink;
109 while u<>source do begin
110 i := from_edge[u];
111 with edge[i] do begin
112 dec(cost);
113 inc(edge[op].cost);
114 inc(ans, w*flow);
115 end;
116 u := from[u];
117 end;
118 end;
119 end;
120
121 procedure print;
122 begin
123 writeln(ans);
124 end;
125
126 begin
127 assign(input,'aaa.in'); reset(input);
128 init;
129 main;
130 print;
131 end.



posted @ 2012-04-06 19:44  F.D.His.D  阅读(306)  评论(0编辑  收藏  举报