以下是给定的输入集。
1009 2000
1009 2001
1002 2002
1003 2002
每行代表一个组,Number代表组中成员的ID。问题是选择重新呈现完整给定集的最小人数。每个组只能选择一名成员。 2元组成员不会重复。但成员可以成为不止一个群体的一部分。
因此,在此示例中,答案为1009
和2002
,代表集合。选择1009
是因为它代表两个团队,2002
的情况也是如此。
我正在寻找可用于解决此问题的算法。
另一个例子:
1009 2000
1009 2001
1002 2002
1003 2002
1004 2003
答案可以是{ 1009 , 2002, 1004}
或{ 1009, 2002, 2003}
答案 0 :(得分:3)
实际上,Sodved给出的例子表明我错了。它不是由边缘覆盖解决的,因为它仍然存在选择实际顶点的问题。
答案 1 :(得分:0)
你留下了一些细节,所以我做了以下假设。如果他们错了,请告诉我。
因此,如果您将每个数字视为图形中的顶点,并将每行输入视为两个顶点之间的边缘,那么您得到的是bipartite graph - 一组“第一个数字”和一组“第二个数字”,以及它们之间的边缘。现在,将图表分解为每个connected components。在每个连接的组件中,您必须选择所有“第一个数字”或所有“第二个数字”。因此,对于每个连接的组件,选择这两个选项中较小的一个是较小的组。
答案 2 :(得分:0)
如果有人有兴趣,这里有一些笨拙无用的perl代码似乎可以解决这个问题。使用大型数据集需要一段时间。我确信事情可以做得更好,特别是他生成索引排列(sequences
)。
#!/usr/bin/perl
# http://stackoverflow.com/questions/6689147/
use strict;
use warnings;
# Return array of arrays with every possible sequence of 0..n-1
sub sequences($);
sub sequences($)
{
my $n = $_[0];
my @ret;
if( $n > 0 )
{
for( my $i=0; $i<$n; $i++ )
{
my @a = sequences( $n-1 );
foreach my $br (@a)
{
my @b = @$br;
splice( @b, $i, 0, $n-1 );
push( @ret, \@b );
}
}
}
else
{
@ret = ( [] );
}
return @ret;
} # END sequences
# Remove elements from set which are covered by later elements in set
sub stripset($$)
{
my( $data, $set ) = @_;
my $strip = 0;
my %cover;
for( my $i=0; $i<scalar(@$set); $i++ )
{
my $covered;
for( my $j=scalar(@$set)-1; $j>$i; $j-- )
{
if( $data->{$set->[$j]}->{$set->[$i]}
&& !$cover{$set->[$i]} )
{
$covered = 1;
$cover{$set->[$j]} = 1;
last;
}
}
if( $covered )
{
$strip = $i+1;
}
else
{
last;
}
}
if( $strip )
{
splice( @$set, 0, $strip );
}
} # END stripset
# Load input
my %links;
while( my $line = <STDIN> )
{
if( $line =~ /^\s*(\S+)\s+(\S+)\s*$/ )
{
$links{$1}->{$2} = 1;
$links{$2}->{$1} = 1;
}
else
{
warn "INVALID INPUT LINE: $line";
}
}
my @elems = keys(%links);
my @minset = @elems;
foreach my $seq ( sequences( scalar(@elems) ) )
{
my @set = map( $elems[$_], @$seq );
#print "TEST set: " . join( ' ', @set ) . "\n";
stripset( \%links, \@set );
#print "STRP set: " . join( ' ', @set ) . "\n";
if( scalar(@set) < scalar(@minset) )
{
@minset = @set;
}
}
print "Shortest set: " . join( ' ', @minset ) . "\n";
答案 3 :(得分:0)
只是想注意这个要求
每个小组只能选择一名成员。
没有多大意义。如果你强制执行,这个简单的问题
1 2
2 3
3 1
没有解决方案。