POJ 1287 Networking

本文详细介绍了求解最小生成树问题的两种经典算法——克鲁斯卡尔算法和普利姆算法。通过具体实例展示了如何使用这两种算法实现节点间的最优连接,并提供了完整的C++代码实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

这里写图片描述
这里写图片描述

题目大意:给出n个节点,再有m条边,这m条边代表从a节点到b节点电缆的长度,现在要你将所有节点都连起来,并且使长度最小

解题思路:求最小生成树众所周知 有两种算法,一种是普利姆算法,一种是克鲁斯卡尔算法 克鲁斯卡尔是与并查集有关的算法 所以可以用两种算法来解决这道题 由于基本是模板题 并没有什么要讲的

克鲁斯卡尔算法

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <algorithm>
#include <map>
#include <cmath>
#include <queue>
#include <string>
#include <vector>
#include <set>

using namespace std;

#define ll long long
#define sc(x) scanf("%d",&x)
#define dsc(x,y) scanf("%d%d",&x,&y)
#define pr(x) printf("%d\n",x)
#define FOR(i,n,o) for(int i=o;i<=n;i++)
#define lcr(a,b)  memset(a,b,sizeof(a))
#define Inf 1<<29
#define N 2005


int n,m,sum,total;
int p[N];
struct node
{
    int f;
    int t;
    int v;
}q[N];
int cmp(node a,node b)
{
     return a.v<b.v;
}
int find(int x)
{
    if(x!=p[x])
    {
        p[x]=find(p[x]);
    }
    return p[x];
}
int pri()
{
        sum=0;
        total=0;
        FOR(i,m,1)
        {
             int f=q[i].f;
             int t=q[i].t;
             if(find(f)!=find(t))
             {
                  p[find(f)]=find(t);
                  sum+=q[i].v;
                  total++;
             }
             if(total==n-1)
                return sum;
        }
        return 0;
}
int main()
{
    while(~dsc(n,m))
    {
        if(n==0)
        break;
        FOR(i,n,1)
        {
            p[i]=i;
        }
        FOR(i,m,1)
        {
            scanf("%d %d %d",&q[i].f,&q[i].t,&q[i].v);
        }
        sort(q+1,q+1+m,cmp);
        pr(pri());
    }
    return 0;
}

这里写图片描述

普利姆算法

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <algorithm>
#include <map>
#include <cmath>
#include <queue>
#include <string>
#include <vector>
#include <set>

using namespace std;

#define ll long long
#define sc(x) scanf("%d",&x)
#define dsc(x,y) scanf("%d%d",&x,&y)
#define pr(x) printf("%d\n",x)
#define FOR(i,n,o) for(int i=o;i<=n;i++)
#define lcr(a,b)  memset(a,b,sizeof(a))
#define Inf 1<<29
#define N 2005

int n,m;
int mp[105][105],dis[N],vis[N];
int pri()
{
         int sum=0;
         FOR(i,n,1)
         {
             dis[i]=mp[1][i];
         }
         vis[1]=1;
         FOR(i,n-1,1)
         {
             int to=-1;
             int minn=Inf;
             FOR(j,n,1)
             {
             if(!vis[j]&&dis[j]<minn)
              {
                  to=j;
                  minn=dis[j];
              }
         }
         if(to==-1)
          return 0;
          vis[to]=1;
          sum+=minn;
          FOR(j,n,1)
          {
              if(!vis[j])
                dis[j]=min(dis[j],mp[to][j]);
          }
         }
         return sum;
}
int main()
{
    while(~sc(n),n)
    {
        lcr(vis,0);
       FOR(i,n,1)
       {
           FOR(j,n,1)
           mp[i][j]=Inf;
       }
        sc(m);
        FOR(i,m,1)
        {
            int f,t,v;
            scanf("%d %d %d",&f,&t,&v);
            mp[f][t]=mp[t][f]=min(v,mp[t][f]);
        }
        pr(pri());
    }
    return 0;
}

这里写图片描述

END!!!!!!!!!!!!!!!!!!

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值