Time Limit: 1000MS | Memory Limit: 10000K | |
Total Submissions: 56761 | Accepted: 23531 |
Description
Farmer John ordered a high speed connection for his farm and is going to share his connectivity with the other farmers. To minimize cost, he wants to lay the minimum amount of optical fiber to connect his farm to all the other farms.
Given a list of how much fiber it takes to connect each pair of farms, you must find the minimum amount of fiber needed to connect them all together. Each farm must connect to some other farm such that a packet can flow from any one farm to any other farm.
The distance between any two farms will not exceed 100,000.
Input
Output
Sample Input
4 0 4 9 21 4 0 8 17 9 8 0 16 21 17 16 0
Sample Output
28
最小生成樹裸題,用prim或kruskal算法。
prim:
#include<iostream>
#include<cmath>
using namespace std;
int n;///點的數量
int mapp[101][101];///存鄰接表
int dis[101];///表示每個點到生成樹的距離
int inf=0xfffffff;
int min_node;///距離生成樹最近的點
int min_arc;///距離生成樹最近的點與生成樹的距離(權值)
int sum;///最小生成樹權值和
int min(int a,int b)
{
return a<b?a:b;
}
void prim()
{
int now;///表示符合加入生成樹的點
sum=0;
for(int i=1;i<=n;i++)
dis[i]=inf;
now=1;///第一個點是起始點
for(int i=1;i<n;i++)
{
dis[now]=-1;///將now點加入生成樹
min_arc=inf;
for(int j=1;j<=n;j++)///把剩下的點到生成樹的距離刷新一遍
{
if(now!=j && dis[j]>=0)///判斷是不是生成樹中的點
{
dis[j]=min(dis[j],mapp[now][j]);
if(dis[j] < min_arc)///找到下一個加入生成樹的點
{
min_arc=dis[j];
min_node=j;
}
}
}
now=min_node;
sum+=min_arc;
}
}
int main()
{
while(cin>>n){
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
cin>>mapp[i][j];
prim();
cout<<sum<<endl;}
return 0;
}
kruskal:
#include<iostream>
#include<algorithm>
using namespace std;
struct edge
{
int u,v,w;
};///定義邊
int p[110];///並查集
edge e[110*110];
int n,ne;///節點數,邊數
int cmp(edge &a,edge &b)
{
return a.w < b.w;
}
int find(int i)///返回p[i]所在樹的樹根
{
return p[i]==i?i:p[i]=find(p[i]);
}
bool union_set(int a,int b)
{
a=find(a);
b=find(b);
if(a!=b)///沒有共同祖先
{
p[a]=b;///將節點納入最小生成樹集合中
return true;
}
else
return false;
}
int kruskal()
{
int mst_edge=0,sum=0;
for(int i=1;i<=n;i++)///初始化並查集
p[i]=i;
sort(e,e+ne,cmp);///將邊按升序排序
for(int i=0;i<ne;i++)
{
///如果加入的邊不會使樹形成迴路
if(union_set(e[i].u,e[i].v))
{
sum+=e[i].w;
if(++mst_edge==n-1)
return sum;
}
}
return mst_edge;
}
int main()
{
int cost;
while(cin>>n)
{
ne=0;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
cin>>cost;
if(i!=j)
{
e[ne].u=i;
e[ne].v=j;
e[ne++].w=cost;
}
}
}
cout<<kruskal()<<endl;
}
return 0;
}