Prim算法大致介绍(个人理解)
1:图中所有的点组成了一个集合set,从集合set中随意选取一个点s,开始进行该算法,
2:从set中将该点s删除,并将该点s加入到另外一个集合now中,now初始为空
3:对now中的所有节点进行遍历,找到距离now的最近的那个非集合now的节点,并将该节点从set中删除,加入now中,
4:重复步骤3,直到set集合为空
无向图:
#include<map> #include<vector> #include<string> #include<set> #include<queue> #include<limits> #include<iostream> using namespace std; queue<string> pre; //存放所有元素的一个队列,数据输入完队列就建立好了,算法开始后队列元素依次出队列,进入now中,队列为空时说明所有节点都已经遍历完全 vector<string> now; //存放从队列出来的元素,即已经找到路径的节点,用vector便于取数据 set<string> nowset; //用set存放从队列出来的元素,便于查找 map<string, vector<string> > relation; //存放节点和与该节点相邻节点的关系 int prim(map<string, map<string, int> > link) //prim算法。贪心策略,最小生成树 { string head; int total = 0; head = pre.front(); //选取一个节点为最先开始进行该算法的点 pre.pop(); //从队列弹出,并且进入now中 now.push_back(head); nowset.insert(head); while (!pre.empty()) { int i = 0,j=0,min=0,flag=0; string start, end; //遍历已经找到路径的节点(now中的节点),找这些节点的邻接节点,每一个路径都会有个权值,找到最小权值,则此次循环可以添加一个节点进入 //now中,同时添加一条路径 for (i = 0; i < now.size(); i++) { for (j = 0; j < relation[now[i]].size(); j++) { if (nowset.find(relation[now[i]][j]) == nowset.end()) //在nowset里没有该元素,则找最小权值 { if (flag == 0) //每当now新添加了元素,都要进行一次搜索,找到距离now集合最近的那个点,所以每次都要设个flag { min = link[now[i]][relation[now[i]][j]]; //给min赋值,每次对now容器中的元素求最小权值时都要先给min确定个初值 flag = 1; } if (link[now[i]][relation[now[i]][j]] <= min) { min = link[now[i]][relation[now[i]][j]]; //cout << min << endl; start = now[i]; end = relation[now[i]][j]; } } } } cout << "[" << start << "<->" << end << "]" << endl; //打印链路 pre.pop(); now.push_back(end); nowset.insert(end); total += min; } return total; } int main() { map<string, map<string, int> > link; //邻接关系和权值 int x,i=0,y; cin >> x; //邻接关系个数 string s, e; for (i = 0; i < x; i++) { cin >> s >> e >> y; link[s][e] = y; link[e][s] = y; relation[s].push_back(e); relation[e].push_back(s); } map<string, vector<string> >::iterator it; for (it = relation.begin(); it != relation.end(); it++) { pre.push(it->first); } cout << prim(link) << endl; }
//输入: 6 a b 3 a d 6 a c 2 b d 7 b c 5 d c 1 //输出: [a<->c] [c<->d] [a<->b] 6
时间: 2024-10-30 12:29:01