农民约翰被选为他们镇的镇长!他其中一个竞选承诺就是在镇上建立起互联网,并连接到所有的农场。当然,他需要你的帮助。
约翰已经给他的农场安排了一条高速的网络线路,他想把这条线路共享给其他农场。为了用最小的消费,他想铺设最短的光纤去连接所有的农场。
你将得到一份各农场之间连接费用的列表,你必须找出能连接所有农场并所用光纤最短的方案。
每两个农场间的距离不会超过100000
PROGRAM NAME: agrinet
INPUT FORMAT
第一行: | 农场的个数,N(3<=N<=100)。 |
第二行..结尾: | 后来的行包含了一个N*N的矩阵,表示每个农场之间的距离。理论上,他们是N行,每行由N个用空格分隔的数组成,实际上,他们限制在80个字符,因此,某些行会紧接着另一些行。当然,对角线将会是0,因为不会有线路从第i个农场到它本身。 |
SAMPLE INPUT (file agrinet.in)
4
0 4 9 21
4 0 8 17
9 8 0 16
21 17 16 0
OUTPUT FORMAT
只有一个输出,其中包含连接到每个农场的光纤的最小长度。
SAMPLE OUTPUT (file agrinet.out)
28
这一道题的解法是最小生成树:
下面介绍两种最小生成树的算法:
第一种:
由于要连接到所有的农场,那么从任意一个农场出发都可以找到最小解。
进入循环:
1、先查找与新开辟的点直接连接的所有连法。
2、在所有已经开辟的点中查找最小长度的连法且符合条件(不形成环,用标记记录一下就好了)。
3、连接这个点,记录经过的路径。
直到选了N-1条路后即可停止。
第二种:
对所有的路径进行排序,取最小的解且这个解符合条件。这个时候,就有一个新的知识点了。那就是并查集。对于两个集合合并的时候,如果一个个标记,时间复杂度会很高。对于解法在此文中暂不阐述。将最小点连接。取完N-1条边的时候,这就是最小解。
对于第一种解法的代码:
var
ans,i,n,m,p,min,x,y,z,sum,j:longint;
b:array[1..10000,1..2] of longint;
bz:array[1..10000] of boolean;
a:array[1..100,1..100] of longint;
procedure find(k:longint);
var
i:longint;
begin
for i:=1 to n do
begin
if ((bz[i]=false) or (bz[k]=false)) and (a[k,i]>0) then
begin
inc(p);
b[p,1]:=k;
b[p,2]:=i;
end;
end;
end;
begin
read(n);
for i:=1 to n do
for j:=1 to n do
begin
read(a[i,j]);
end;
fillchar(bz,sizeof(bz),false);
p:=0;
find(1);
sum:=1;
while (sum<n) do
begin
min:=0;
for i:=1 to p do
begin
if ((bz[b[i,1]]=false) or (bz[b[i,2]]=false)) and ((min=0) or (a[b[i,1],b[i,2]]<a[b[min,1],b[min,2]])) then
min:=i;
end;
ans:=ans+a[b[min,1],b[min,2]];
find(b[min,2]);
bz[b[min,2]]:=true;
bz[b[min,1]]:=true;
inc(sum);
end;
writeln(ans);
end.