POJ 2942

POJ 2942

题目大意:有n位骑士,他们间有一些仇恨关系,如果有仇恨则开会的时候不能坐在两侧,求至少删除多少名骑士,使得总可以找出奇数个骑士和平地坐下来开会?

解:我挺天真的,一开始就去研究它给出的关系图,想了好久才去建补图。发现如果是可以坐在一起的话补图上就是一个圈,任务就是找奇圈,然后自己草莽地写了一个边双连通分量算,wa,调了略久,没思路,看题解,发现是点双连通(边双连通内可能有关节点,但是点双连通内一定没有桥,所以如果只是算出边双连通可能会因当中包含关节点而出错),况且我也是理解错题意了,我以为是找最大奇圈,但实际上是把所有的可能都算出来。正解首先是求点双连通,没找到一个块,对这个块进行染色。这里略略吐槽一下网上的说法,根本不是二分图么,只是用了验证二分图的更新方法。然后则是用了一个性质:如果块内有一个奇圈,那么这个块内的其他点也必定在某个奇圈上。(理解:如果块内的点位奇数,那么剩下的偶数点一定是在同一个奇圈(因为没有桥与关节点,一定可以组成回路),如果是偶数点,那么偶数-奇数=奇数,显然)注意题意1个点是不能算数的,但你也不同特殊计算,如果是染色找到一个奇圈后只有单个点剩下的话那么它一定是其他块内的点,作为一个关节点存在。

View Code
  1 //poj 2942
2 const
3 maxn=1111;
4 maxm=maxn*maxn;
5 type
6 data=record
7 dest, next: longint;
8 end;
9 var
10 edge: array[1..maxm]of data;
11 g: array[1..maxn, 1..maxn]of boolean;
12 bcc, col, cnt, vect, pre, low, dfn: array[1..maxn]of longint;
13 stack: array[1..maxn, 0..1]of longint;
14 visit: array[1..maxn]of boolean;
15 key, ffff, color, ans, tot, n, m, time, stot: longint;
16 procedure add(x, y: longint);
17 begin
18 inc(tot);
19 with edge[tot] do begin
20 dest := y;
21 next := vect[x];
22 vect[x] := tot;
23 end;
24 inc(tot);
25 with edge[tot] do begin
26 dest := x;
27 next := vect[y];
28 vect[y] := tot;
29 end;
30 end;
31
32 {procedure del(x, y: longint);
33 var
34 i, last: longint;
35 begin
36 if edge[vect[x]].dest = y then begin
37 vect[x] := edge[vect[x]].next;
38 end
39 else begin
40 i := vect[x];
41 while i<>0 do
42 with edge[i] do begin
43 if dest = y then begin
44 edge[last].next := next;
45 break;
46 end;
47 last := i;
48 i := next;
49 end;
50 end;
51
52 if edge[vect[y]].dest = x then begin
53 vect[y] := edge[vect[y]].next;
54 end
55 else begin
56 i := vect[y];
57 while i<>0 do
58 with edge[i] do begin
59 if dest = x then begin
60 edge[last].next := next;
61 end;
62 last := i;
63 i := next;
64 end;
65 end;
66 end; }
67
68 procedure init;
69 var
70 i, j, x, y: longint;
71 begin
72 tot := 0; ans := 0;
73 fillchar(vect, sizeof(vect), 0);
74 {for i := 1 to n-1 do
75 for j := i + 1 to n do add(i, j);
76 for i := 1 to m do begin
77 readln(x, y);
78 del(x, y);
79 end; }
80 fillchar(g, sizeof(g), true);
81 for i := 1 to m do begin
82 readln(x, y);
83 g[x, y] := false; g[y, x] := false;
84 end;
85 for i := 1 to n-1 do
86 for j := i+1 to n do
87 if g[i, j] then add(i, j);
88 end;
89
90 function check(x: longint): boolean;
91 var
92 i, tmp: longint;
93 begin
94 i := vect[x];
95 tmp := (key << 1)+1 - col[x];
96 while i<>0 do
97 with edge[i] do begin
98 if pre[x]<>dest then
99 if bcc[dest]=color then begin
100 if (col[dest]<key) then begin
101 col[dest] := tmp;
102 if check(dest) then exit(true);
103 end
104 else if col[dest]<>tmp then exit(true);
105 end;
106 i := next;
107 end;
108 check := false;
109 end;
110
111 procedure calc_bcc(x, y: longint);
112 var
113 i, tmp: longint;
114 begin
115 tmp := stot;
116 inc(stot); inc(color);
117 repeat
118 dec(stot);
119 bcc[stack[stot][0]] := color; bcc[stack[stot][1]] := color;
120 until ((stack[stot][0]=x)and(stack[stot][1]=y)or(stot=0));
121 if stot>0 then dec(stot);
122 //fillchar(col, sizeof(col), 0);
123 inc(key, 2);
124 col[x] := key;
125 if (check(x)) then begin
126 for i := stot +1 to tmp do begin
127 cnt[stack[i][0]] := 1; cnt[stack[i][1]] := 1;
128 end;
129 end;
130 end;
131
132 procedure tarjan(x: longint);
133 var
134 i: longint;
135 begin
136 visit[x] := true;
137 inc(time);
138 dfn[x] := time; low[x] := time;
139 i := vect[x];
140 while i<>0 do
141 with edge[i] do begin
142 if dest<>pre[x] then begin
143 if dfn[dest]=0 then begin
144 inc(stot);
145 stack[stot][0] := x;
146 stack[stot][1] := dest;
147 pre[dest] := x;
148 tarjan(dest);
149 if low[dest]<low[x] then low[x] := low[dest];
150 if (dfn[x]<=low[dest])or(x=ffff) then begin
151 calc_bcc(x, dest);
152 end;
153 end
154 else if visit[dest] then begin
155 if dfn[dest]<low[x] then low[x] := dfn[dest];
156 end;
157 end;
158 i := next;
159 end;
160 visit[x] := false;
161 end;
162
163 procedure main;
164 var
165 i, u: longint;
166 begin
167 fillchar(dfn, sizeof(dfn), 0);
168 fillchar(pre, sizeof(pre), 0);
169 fillchar(cnt, sizeof(cnt), 0);
170
171 fillchar(col, sizeof(col), 0);
172
173 fillchar(visit, sizeof(visit), 0);
174 fillchar(bcc, sizeof(bcc), 0);
175 time := 0; stot := 0; color := 0; key := 0;
176 for i := 1 to n do if dfn[i]=0 then begin
177 ffff := i; tarjan(i);
178 end;
179 for i := 1 to n do
180 if (cnt[i]=0) then inc(ans);
181 end;
182
183 procedure print;
184 begin
185 writeln(ans);
186 end;
187
188 begin
189 assign(input,'1.txt'); reset(input);
190 readln(n, m);
191 while (n+m<>0) do begin
192 init;
193 main;
194 print;
195 readln(n, m);
196 end;
197 end.



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