PAT 数据结构 06-图6. 公路村村通(30)Prim最小生成树算法
2015-07-16 19:31
411 查看
现有村落间道路的统计数据表中,列出了有可能建设成标准公路的若干条道路的成本,求使每个村落都有公路连通所需要的最低成本。
输入格式说明:
输入数据包括城镇数目正整数N(<=1000)和候选道路数目M(<=3N);随后的M行对应M条道路,每行给出3个正整数,分别是该条道路直接连通的两个城镇的编号以及该道路改建的预算成本。为简单起见,城镇从1到N编号。
输出格式说明:
输出村村通需要的最低成本。如果输入数据不足以保证畅通,则输出-1,表示需要建设更多公路。
样例输入与输出:
用Prim最小生成树算法来写:
已吸收的结点为集合AB,一开始只有1号结点。未吸收的结点为集合UD,一开始包含除1号外的所有结点。每次以最小边的代价将UD中的一个结点吸收到AB。
一开始想到可以用穷举的方法写,当AB集合有k个结点时,UD集合有N-K个,穷举两个集合的所有可能连线,通常来说遍历的效率较低,说得形象点,k每次变化时,每次都要判断1号结点都要与UD集合中的所有结点是否有边,显然第一次之后的判断都是多余的。从这个角度来想,我们每次只要判断AB中最新的一个结点与UD中所有结点是否有边即可。
为了便于操作,定义结点结构体如下面代码所示。由于我是第一次写该算法,多加了前驱结点proNode,用于输出具体的生成树。该变量在本题中是多余的,可以去掉。
输入格式说明:
输入数据包括城镇数目正整数N(<=1000)和候选道路数目M(<=3N);随后的M行对应M条道路,每行给出3个正整数,分别是该条道路直接连通的两个城镇的编号以及该道路改建的预算成本。为简单起见,城镇从1到N编号。
输出格式说明:
输出村村通需要的最低成本。如果输入数据不足以保证畅通,则输出-1,表示需要建设更多公路。
样例输入与输出:
序号 | 输入 | 输出 |
1 | 6 15 1 2 5 1 3 3 1 4 7 1 5 4 1 6 2 2 3 4 2 4 6 2 5 2 2 6 6 3 4 6 3 5 1 3 6 1 4 5 10 4 6 8 5 6 3 | 12 |
2 | 3 1 2 3 2 | -1 |
3 | 5 4 1 2 1 2 3 2 3 1 3 4 5 4 | -1 |
已吸收的结点为集合AB,一开始只有1号结点。未吸收的结点为集合UD,一开始包含除1号外的所有结点。每次以最小边的代价将UD中的一个结点吸收到AB。
一开始想到可以用穷举的方法写,当AB集合有k个结点时,UD集合有N-K个,穷举两个集合的所有可能连线,通常来说遍历的效率较低,说得形象点,k每次变化时,每次都要判断1号结点都要与UD集合中的所有结点是否有边,显然第一次之后的判断都是多余的。从这个角度来想,我们每次只要判断AB中最新的一个结点与UD中所有结点是否有边即可。
为了便于操作,定义结点结构体如下面代码所示。由于我是第一次写该算法,多加了前驱结点proNode,用于输出具体的生成树。该变量在本题中是多余的,可以去掉。
/*2015.7.16cyq*/ //Prim最小生成树算法 #include <iostream> #include <vector> #include <fstream> #include <algorithm> using namespace std; const int MAX=2147483647; //ifstream fin("case1.txt"); //#define cin fin struct node{ int num; //结点序号 int weight; //能连通到已确定子图的最小边 int preNode;//最小边依附的结点,用于输出具体生成树 node():num(-1),weight(-1),preNode(-1){} node(int n,int wei,int preN):num(n),weight(wei),preNode(preN){} bool operator < (const node &a) const{ return weight<a.weight; } }; int main(){ int N,M; cin>>N>>M; vector<vector<int> > edges(N+1,vector<int>(N+1,-1));//-1表示不连通 int a,b,c; while(M--){ cin>>a>>b>>c; edges[a][b]=c; edges[b][a]=c; } vector<node> AB;//已吸收的点,一开始只有结点1 AB.push_back(node(1,0,-1));// vector<node> UD(N-1);//未吸收的点 for(int i=0;i<N-1;i++){ UD[i].num=i+2;//编号2到N int tmp=edges[1][UD[i].num]; if(tmp>0){//能连到结点1的结点 UD[i].weight=tmp; UD[i].preNode=1; }else{//不能连到结点1的结点 UD[i].weight=MAX; UD[i].preNode=-1; } } int totalLength=0; //vector<pair<int,int> > result;//用于输出具体生成树 while(!UD.empty()){ sort(UD.begin(),UD.end()); node cur=UD[0];//取出能以最小代价吸收的点 UD.erase(UD.begin()); if(cur.weight==MAX){ cout<<"-1"<<endl; return 0; } totalLength+=cur.weight; // result.push_back(make_pair(cur.num,cur.preNode)); for(auto it=UD.begin();it!=UD.end();++it){//用该点修正未吸收的点 int w=edges[cur.num][(*it).num]; if(w>0){ if(w<(*it).weight){ (*it).weight=w; (*it).preNode=cur.num; } } } } cout<<totalLength<<endl; //for(auto it=result.begin();it!=result.end();++it){//输出最小生成树 // cout<<(*it).first<<" "<<(*it).second<<" "<<edges[(*it).first][(*it).second]<<endl; //} return 0; }事实上,可以进一步把UD集合分成两个集合,第一个集合中的点与AB相邻,第二个集合的点与AB不相邻,尚未探测到。这样每次只要对第一个集合进行排序,取出最小值进行操作即可。
相关文章推荐
- 数据结构复习之树
- 数据结构之位图
- 数据结构与算法分析 note
- 数据结构与算法五
- 数据结构与算法四
- 数据结构与算法三
- 数据结构与算法二
- 数据结构与算法一
- 线索化二叉树
- 跟我学数据结构之基本概念
- C++一些基本数据结构:字面常量、符号常量、枚举常量
- List中的每个元素,两两为一对(不包括自身)组合
- 数据结构基础 之 二叉堆 概念篇
- 《大话数据结构》第2章 算法基础 2.9 算法的时间复杂度
- 《大话数据结构》第2章 算法基础 2.8 函数的渐近增长
- 《大话数据结构》第1章 数据结构绪论 1.2 你数据结构怎么学的?
- 《大话数据结构》第1章 数据结构绪论 1.1 开场白
- PAT 数据结构 06-图5. 旅游规划(25)Dijkstra最短路径算法
- 数据结构(一)顺序表、链表以及队列
- 第13章 数据结构基础