Description
In order to lower the risk of riots and escape
attempts, the boards of two nearby prisons of equal prisoner
capacity, have decided to rearrange their prisoners among
themselves. They want to exchange half of the prisoners of one
prison, for half of the prisoners of the other. However, from the
archived information of the prisoners' crime history, they know
that some pairs of prisoners are dangerous to keep in the same
prison, and that is why they are separated today, i.e. for every
such pair of prisoners, one prisoners serves time in the first
prison, and the other in the second one. The boards agree on the
importance of keeping these pairs split between the prisons, which
makes their rearrangement task a bit tricky. In fact, they soon
find out that sometimes it is impossible to fulfil their wish of
swapping half of the prisoners. Whenever this is the case, they
have to settle for exchanging as close to one half of the prisoners
as possible.
Input
On the first line of the input is a single
positive integer n, telling the number of test scenarios to follow.
Each scenario begins with a line containing two non-negative
integers m and r, 1 < m < 200 being
the number of prisoners in each of the two prisons, and r the
number of dangerous pairs among the prisoners. Then follow r lines
each containing a pair xi yi of integers in the range 1 to m,which
means that prisoner xi of the first prison must not be placed in
the same prison as prisoner yi of the second prison.
Output
For each test scenario, output one line containing
the largest integer k <= m/2 , such that it is
possible to exchange k prisoners of the first prison for k
prisoners of the second prison without getting two prisoners of any
dangerous pair in the same prison.
題目大意:有兩個監獄都有n人,要分別抽調不多於n div
2的人交換。原先兩個監獄之間有些犯人對必須在不同的監獄。給出e對犯人不能同在一個監獄。求最大交換數。
//===========================================================================
把給出的每對犯人連雙向邊,求出聯通塊,容易發現一個聯通塊裏要換一起換。求有幾個聯通塊,做01揹包。輸出f[max,max]。
嗯。這裏註明一下。今天WA了將近十次,因爲循環變量應該從大到小for,不然一個塊會取很多遍。。。揹包都編挫了。。。。。。。。。。。。。。
還有,這題內存限制很小。。。大家自重。。。。
AC CODE
program pku_1636;
var map:array[1..400,0..200] of longint;
p:array[1..400] of boolean;
w:array[0..1,1..400] of longint;
f:array[0..100,0..100] of boolean;
i,tot,len,size,n:longint;
//============================================================================
procedure dfs(u:longint);
var v,i:longint;
begin p[u]:=true;
if u>n then inc(w[1,size])
else
inc(w[0,size]);
for i:=1 to map[u,0] do
if
not(p[map[u,i]]) then
dfs(map[u,i]);
end;
//============================================================================
procedure work;
var m,i,j,k,x,y:longint;
begin
readln(n,m);
fillchar(map,sizeof(map),0);
for i:=1 to m do
begin
readln(x,y);
inc(y,n);
inc(map[x,0]); map[x,map[x,0]]:=y;
inc(map[y,0]); map[y,map[y,0]]:=x;
end; size:=0;
fillchar(p,sizeof(p),0);
for i:=1 to n*2 do
if not(p[i])
then
begin
inc(size); w[0,size]:=0;
w[1,size]:=0; dfs(i);
end;
fillchar(f,sizeof(f),0);
f[0,0]:=true; n:=n div 2;
for k:=1 to size do
for i:=n
downto w[0,k] do
for j:=n downto w[1,k] do
f[i,j]:=f[i-w[0,k],j-w[1,k]] or f[i,j];
for i:=n downto 0 do
if f[i,i]
then
begin
writeln(i);
exit;
end;
end;
//============================================================================
begin
readln(tot);
for i:=1 to tot do work;
end.