【二分+染色】集合划分(Partition)

 

集合划分(Partition)

[问题描述]   

 

    给定一个集合X = {x1, x2, x3…xn}。

    定义函数D[xu, xv]:D[xu, xv] = D[xv, xu]且D[xu, xu] = 0。

    一个partition是指一种将X划分为K个不相交的子集T = (C1, C2…CK)。CP是X的一个非空子集。

定义一个partition的费用Cost(T) = min{D[u, v]},其中u属于Cp、v属于Cq且有p <>q。

[编程任务]

给定N、K和D,求一个划分使其费用最大。

[输入文件]input.txt。

N  K

然后一个N * N的矩阵,第i行j列描述D[i, j]。

[输出文件]output.txt。

你所找到的最大费用。

[样例输入输出]

Input.txt

4 3

0 1 2 3

1 0 2 3

2 2 0 3

3 3 3 0

 

Output.txt

2

[数据约定]

1 < k <= n <= 200

0 <= D[u, v] <= 32000

对于50%的数据满足k <= 10

===========================

 数细胞问题

==================================

var
  map:array[1..200,1..200]of longint;
  f_bo:array[1..200]of boolean;
  dui:array[1..200000]of longint;
  n,k,max,k_s:longint;
  
procedure init;
begin
  assign(input,'partition.in');
  assign(output,'partition.out');
  reset(input); rewrite(output);
end;

procedure terminate;
begin
  close(input); close(output);
  halt;
end;

procedure bfs(t,std:longint);
var
  l,r:longint;
  i:longint;
  x:longint;
begin
  l:=0; r:=1;
  dui[1]:=t;
  repeat
    inc(l);
    x:=dui[l];
    for i:=1 to n do
      if (f_bo[i])and(map[x,i]<std) then
        begin
          f_bo[i]:=false;
          inc(r);
          dui[r]:=i;
        end;
  until l>=r;
end;


function pd(std:longint):boolean;
var
  i:longint;
  k_s:longint;
begin
  fillchar(f_bo,sizeof(f_bo),true);
  k_s:=0;
  for i:=1 to n do
    if f_bo[i] then
      begin
        f_bo[i]:=false;
        bfs(i,std);
        inc(k_s);
      end;
  if k_s>=k then exit(true)
            else exit(false);
end;

procedure main;
var
  i,j:longint;
  l,r,m:longint;
  ans:longint;
begin
  readln(n,k);
  if n=k then
    begin
      max:=maxlongint;
      for i:=1 to n do
        for j:=1 to n do
          begin
            read(map[i,j]);
            if (max>map[i,j])and(i<>j)then max:=map[i,j];
          end;
      writeln(max);
      terminate;
    end
    else
    begin
      max:=0;
      for i:=1 to n do
        for j:=1 to n do
          begin
            read(map[i,j]);
            if max<map[i,j] then max:=map[i,j];
          end;
          
      l:=0; r:=max;
      while l<=r do
        begin
          m:=(l+r) shr 1;
          if pd(m) then
            begin
              ans:=m;
              l:=m+1;
            end
            else r:=m-1;
        end;
    end;
  writeln(ans);
end;

begin
  init;
  main;
  terminate;
end.


 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值