请问哪里有这两个问题的算法代码呢?

arbutus 2003-10-12 04:50:49
一个是关于无向图的最小覆盖集算法,就是:
在图G=(V,E)中找一顶点集S,使得对任意(u,v)∈E有u∈S或v∈S,
且|S|最小。
这个问题是不是没有很好的算法呢?如果没有近似的算法也可以,但要图的不要数的。


另一个是关于赋权图的重心的算法,就是在一个图中,节点都有权值,寻找图的重心。

谁有这两个问题的代码能共享给我一份么?
谢谢了先!!
...全文
20 4 打赏 收藏 转发到动态 举报
写回复
用AI写文章
4 条回复
切换为时间正序
请发表友善的回复…
发表回复
jwd_1_cool 2003-10-14
  • 打赏
  • 举报
回复
谢谢 one_add_one()我要睡觉:大大!!
one_add_one 2003-10-14
  • 打赏
  • 举报
回复
第二个问题曾经是 电脑爱好者的 擂台赛题目.

先找两个点,然后求这两个点组成的重心,然后把这个重心代替那两个点...

继续下去,只剩一个点的时候就是 图形的重心了
apogeecsj 2003-10-13
  • 打赏
  • 举报
回复
gz!
zzwu 2003-10-12
  • 打赏
  • 举报
回复

在图G=(V,E)中找一顶点集S,使得对任意(u,v)∈E有u∈S或v∈S,且|S|最小。
这是求图的最小顶点覆盖集。

【算法分析】

  图的最小顶点覆盖是NP问题,至今还没有有效算法。而本题N的规模可达1500,显然用搜索是无法完成的。但本题的图十分特殊是一棵树。为了进一步利用数据结构的特殊性,我们不妨先手工分析一个例子。左图为一个有13个顶点的树,其中用红色圈出的顶点为找到的最小覆盖集。很明显,叶节点不可能属于覆盖集,但叶节点的父节点一定属于覆盖集,以此为基础再判断上一层次节点是否属于覆盖集。左图的节点编号从大到小正好是我们判断的顺序,该顺序恰好是树的前序遍历顺序,由此我们可得出本题的算法:

  1:procedure Min-Vertex-Cover(T);
  2:begin
  3:  按前序遍历顺序重新编排整棵树的节点编号。
  4:  for I:=1 to n do cover[I]:=0;
  5:  for I:=n Downto 2 do
  6:   if (cover[I]=0) and (cover[parent[I]]=0) then
  7:     cover[parent[I]]:=1;
  8:end;
  
  该算法是一个贪心算法。算法中用数组cover来标记选入覆盖点集的树结点,即当结点i被选入覆盖点集,则cover[i]=1,否则cover[i]=0。为了说明算法的正确性,必须证明关于树的最小顶点覆盖问题满足贪心选择性质并且具有最优子结构性质。具体的证明过程,在《若干NP完全问题的特殊情形》一文中已有详细的叙述。
  最后我们分析一下算法的复杂度,前序遍历树显然可以在O(n)时间内完成,再加上for循环显然需要O(n)的时间,从而整个算法所需的时间为O(n)。对于本题的规模,完全可以接受了。

【小结】
  本题的数学模型是一个NP问题,然而在树这样一个特殊结构下,我们充分利用题目中的已知信息,降低了题目的难度,找到了线性时间的算法。通过解这道题我认识到充分利用题目信息的重要性,一个算法越体现出题目的特征,效率也就越高,当然它的适用范围也就越狭窄,这也正是构造法解题之所以高效的原因。

【参考文献】
《若干NP完全问题的特殊情形》 《福州大学学报》99.5 王晓东

【附录】
源程序:Strategi.pas

Program exp;
Var count,m,tmp,k,j,i,n:Integer;
  Convert,Parent,Cover:Array [0..1500] Of Integer; {Convert[I]:节点I的前序遍历标号;      Parent[I]:指出节点I的父亲节点;Cover[I]:是否覆盖节点[I]}
Procedure Preorder(root:Integer); {树的前序遍历、标号过程}
Var i,j,k:Integer;
Begin
 Convert[count]:=root;Inc(count);
 For i:=1 To n Do
  If Parent[i]=root Then Preorder(i);
End;
Begin
 Assign(input,'input.txt');Reset(input);
 Assign(output,'output.txt');Rewrite(output);
 {初始化并读入数据}
 Readln(n);
 For i:=0 To n Do parent[i]:=-1;
 For i:=1 To n Do Begin
  Read(j,m);
  For k:=1 To m Do Begin
   Read(tmp);Parent[tmp]:=j;
  End;
  Readln;
 End;
 Fillchar(cover,sizeof(cover),0);
 count:=1;i:=-1;Repeat Inc(i) Until Parent[i]=-1;
 Preorder(i);count:=0;
 For i:=n Downto 2 Do {贪心算法}
  If (cover[Convert[i]]=0) and (Cover[parent[Convert[i]]]=0) Then Begin
    cover[parent[Convert[i]]]:=1;
    Inc(count);
  End;
 Writeln(count);
 Close(output);
End.


引自:

http://www.chinaschool.org/aosai/lwjl/zryx.htm

33,008

社区成员

发帖
与我相关
我的任务
社区描述
数据结构与算法相关内容讨论专区
社区管理员
  • 数据结构与算法社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧