prim算法的前向星实现

最小生成树算法实现
#include <map>
#include <set>
#include <stack>
#include <queue>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int INF=0x3f3f3f3f;
const int maxn=100;
const int maxm=maxn*maxn;
struct Edge {
    int from,to,w,next;
};

int n,m;
int pre[maxn];//前向星存储法
Edge e[maxm]; //存储边集
bool vis[maxn]; //判断是否已加入生成树集合
int dis[maxn]; //未确定点集到已确定点集的距离

int main()
{
#ifdef LOCAL_DEBUG
freopen("input.txt","r",stdin);
#endif
    while(~scanf("%d%d",&n,&m) && n+m)
    {
        memset(pre,-1,sizeof(pre));
        memset(vis,0,sizeof(vis));

        //假设无自环
        int from,to,w;
        for(int i=0;i<m;i++) //无向图的存储
        {
            scanf("%d%d%d",&from,&to,&w);
            e[i].from=from; e[i].to=to; e[i].w=w;
            e[i].next=pre[from]; pre[from]=i;
            std::swap(from,to);
            e[i+m].from=from; e[i+m].to=to; e[i+m].w=w;
            e[i+m].next=pre[from]; pre[from]=i+m;
        }

        memset(dis,INF,sizeof(dis));
        dis[1]=0; 
        int ans=0;
        for(int i=0;i<n;i++) //每次确定最小生成树的一个节点,n次确定n个节点
        {
            int minw=INF,v;
            for(int x=1;x<=n;x++) //从候选点集中选择距离已确定点集最短的边
            {
                if(!vis[x] && dis[x]<=minw)
                {
                    minw=dis[x];v=x;
                }
            }
            ans+=minw;
            vis[v]=true; //标记找到的点
            for(int k=pre[v];k!=-1;k=e[k].next) //利用此点更新候选点集各个点到已确定点集的距离
            {
                if(e[k].w<dis[e[k].to] && !vis[e[k].to])
                {
                    dis[e[k].to]=e[k].w;
                }
            }
        }
        printf("%d\n",ans);
    }
    return 0;
}

### 关于Prim算法中的数据输入方式 在Prim算法中,通常会处理带权无向图来构建最小生成树。为了实现这一目标,需要一种合适的方式来表示图的结构及其边权重。常见的图表示方法有邻接矩阵和邻接表两种形式。 #### 邻接矩阵表示法 邻接矩阵是一种二维数组的形式用于存储图的信息。对于一个具有 \(n\) 个顶点的图,可以创建一个大小为 \(n \times n\) 的矩阵 `graph` 来记录每一对顶点之间的连接关系及对应的权重。如果两个顶点之间存在一条边,则该位置存入相应的权重;如果没有直接相连,则可以用无穷大(如 INT_MAX 或者一个非常大的数)或者零来标记[^1]。 例如,在C语言中定义如下: ```c #define INF 99999 int graph[V][V]; ``` 这里假设常量 V 表示节点数量的最大值,并初始化整个 matrix 数组为INF代表初始状态下任意两点间均不存在路径[^2]。 接着通过读取具体边信息填充此matrix, 假设文件里给出的是三元组(u,v,w),分别对应起点u终点v还有它们间的距离w: ```c for (i = 0; i < edges_count; ++i){ scanf("%d %d %d", &start_vertex[i], &end_vertex[i], &weight[i]); graph[start_vertex[i]][end_vertex[i]] = weight[i]; graph[end_vertex[i]][start_vertex[i]] = weight[i]; // 如果是无向图的话还需要加上这句 } ``` 上述代码片段展示了如何基于标准输入流获取边的相关参数并将这些数值填入预先准备好的邻接矩阵当中去[^3]。 #### 邻接列表表示法 另一种常用的方法就是采用链式向星或者是vector容器构成的邻接列表表达图形。这种方法更加节省空间尤其当稀疏图的时候显得尤为重要。每一个结点关联着一系列指向其他相邻节点指针连同其上的代价一同保存下来形成所谓的邻居清单。 下面是一个简单的例子展示怎样利用STL vector建立这样的结构: ```cpp #include <bits/stdc++.h> using namespace std; struct Edge { int to; int cost; }; const int MAXN = 1e5 + 7; vector<Edge> adjList[MAXN]; // 添加边到邻接表中 void addEdge(int u,int v ,int w ){ adjList[u].push_back({v,w}); adjList[v].push_back({u,w}); // 对于无向图而言也需要反方向加一次 } int main(){ ios::sync_with_stdio(false); cin.tie(0); int nodes,edges; cin>>nodes>>edges; while(edges--){ int a,b,cost; cin >>a>>b>>cost; addEdge(a,b,cost); } return 0; } ``` 以上程序段落先声明了一个最大容量足够容纳所有可能存在的定点数目上限的大规模静态数组adjList[][],其中每个元素都是动态增长型别的vector对象专门用来装载那些隶属于当索引编号所指示的那个特定顶点的所有直系子代们各自的资料详情包括但不限于他们自己的身份识别号码to以及彼此沟通所需支付的价格成本cost等等属性特征值不一而足. 无论是哪种表现手法最终目的皆是为了方便后续执行prim核心逻辑运算过程能够顺利取得必要的拓扑资讯而已.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值