poj 1634 Prison rearrangement

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.
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章