算法思想:贪心,从边出发。要找出最小生成树,可以每一步都找一个边权尽量小的边,并且这个边连接的两个点没有被已经选的边链接(直接链接,或者间接链接)。这样每一步都找的是符合当前情况的最小边,那么结果自然也是最小的。
复杂度:O(ElogE) 适合稀疏图
步骤:
算法思想:贪心,从点出发。定义两个集合A储存所有的点,B储存选了的点。先随机确定一个起点放入集合A,每次从剩下的点中选择到A集合距离最小的点加入集合A。把所有点都放入A,将得到的距离求和。
复杂度:O(n^2) 适合稠密图
步骤:
分割线
HDU-畅通工程AC代码:
#include
using namespace std;
const int maxn=1E5+5;
const int INF=1<<30;
int n,m,cnt;
int pre[maxn];
struct node
{
int from,to,val;
}qwe[maxn];
bool cmp (node a,node b)
{
return a.val<b.val;
}
int unionsearch (int root)
{
int son,tmp;
son=root;
while (root!=pre[root])
root=pre[root];
while (son!=root)
{
tmp=pre[son];
pre[son]=root;
son=tmp;
}
return root;
}
void join (int x,int y)
{
if (unionsearch(x)!=unionsearch(y))
pre[unionsearch(x)]=unionsearch(y);
return;
}
void reset()
{
for (int i=1;i<=n;i++)
pre[i]=i;
}
int kruskal ()
{
int mst=0;
int x,y;
int num=0;
sort(qwe+1,qwe+1+m,cmp);
reset();
for (int i=1;i<=m;i++)
{
x=qwe[i].from;
y=qwe[i].to;
if (unionsearch(x)!=unionsearch(y))
{
mst+=qwe[i].val;
num++;
join(x,y);
printf ("%d %d %d\n",qwe[i].from,qwe[i].to,qwe[i].val);
if (num>=n-1)
break;
}
}
if (num<n-1)
return -1;
else
return mst;
}
int main ()
{
int a,b,c;
while (~scanf ("%d",&m))
{
if (m==0)
break;
scanf ("%d",&n);
for (int i=1;i<=m;i++)
{
scanf ("%d%d%d",&a,&b,&c);
qwe[i].from=a;
qwe[i].to=b;
qwe[i].val=c;
}
if (kruskal()==-1)
printf ("?\n");
else
printf ("%d\n",kruskal());
}
return 0;
}
#include
using namespace std;
const int maxn=1E3+5;
const int INF=1<<30;
int n,m,cnt;
int mp[maxn][maxn];
int mst[maxn];
int lowcost[maxn];
int prim(int start)
{
int tmp,min_num,ans=0;
mst[1]=1;
for (int i=1;i<=n;i++)
{
lowcost[i]=mp[start][i];
mst[i]=start;
}
mst[start]=-1;
for (int i=1;i<n;i++)
{
min_num=INF;
tmp=-1;
for (int j=1;j<=n;j++)
{
if (mst[j]!=-1&&lowcost[j]<min_num)
{
tmp=j;
min_num=lowcost[j];
}
}
if (tmp==-1)
return -1;
else
{
mst[tmp]=-1;
ans+=lowcost[tmp];
for (int j=1;j<=n;j++)
{
if (mst[j]!=-1&&lowcost[j]>mp[tmp][j]) //如果在集合A中还有点的距离可以通过tmp这个点更新
{
lowcost[j]=mp[tmp][j];//那么就更新
mst[j]=tmp;//并且到tmp这个点才是最小值
}
}
}
}
return ans;
}
void reset()
{
for (int i=1;i<=n;i++)
for (int j=1;j<=n;j++)
{
if (i!=j)
mp[i][j]=INF;
else
mp[i][j]=0;
}
}
int main ()
{
int a,b,c;
while (~scanf ("%d",&m))
{
if (m==0)
break;
scanf ("%d",&n);
reset();
for (int i=1;i<=m;i++)
{
scanf ("%d%d%d",&a,&b,&c);
mp[a][b]=min(mp[a][b],c);
mp[b][a]=min(mp[b][a],c);
}
if (prim(1)==-1)
printf ("?\n");
else
printf ("%d\n",prim(1));
}
return 0;
}