現有村落間道路的統計資料表中,列出了有可能建設成標準公路的若干條道路的成本,求使每個村落都有公路連通所需要的最低成本。
輸入資料報括城鎮數目正整數n(≤1000)和候選道路數目m(≤3n);隨後的m行對應m條道路,每行給出3個正整數,分別是該條道路直接連通的兩個城鎮的編號以及該道路改建的預算成本。為簡單起見,城鎮從1到n編號。
輸出村村通需要的最低成本。如果輸入資料不足以保證暢通,則輸出−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
從題目可以看出,該題目是求能夠連通所有城鎮的最小的道路成本,由最小生成樹的定義可知,該題相當於求城鎮圖的最小生成樹。
第一種方法:
普里姆(prim)演算法:
prim演算法可以成為「加點法」,即每次迭代選擇相連的最小代價邊的對應的點,加入到最小生成樹中。演算法從某乙個頂點s開始,逐漸長大覆蓋整個連通網的所有頂點。如下圖所示:
//prim演算法
#include#include#define maxvex 1005
#define maxedge 3005
#define ifinity 65535
using namespace std;
int g[maxvex][maxvex];
int n,m;//城鎮數目和候選道路數目
int prim()
}if(min_cost != ifinity)}}
}if(numvexes == n)
return minlength;
else
return -1;
}int main()
}for(int i = 0;i < m;i++)
printf("%d",prim());
return 0;
}
這裡的lowcost變數,即為每次更新頂點後所得的代價邊陣列,注意每次更新頂點後需將其對應的lowcost置為0以防止重複判斷。
第二種方法:
克魯斯卡爾(kruskal)演算法 :
此演算法可以稱為「加邊法」,初始最小生成樹邊數為0,每迭代一次就選擇一條滿足條件的最小代價邊,加入到最小生成樹的邊集合裡。
//kruskal演算法
#include#include#define maxvex 1001
#define maxedge 3001
using namespace std;
typedef struct edge;
edge edge[maxedge];
void sortedge(edge *edge, const int& m)
} }}int find_parent(int *parent, int f)
return f;
}int kruskal(edge* edge, const int &n, const int &m)
for (int i = 0; i < m; i++) }
if (numedges == n-1)
return minlength;
else
return -1;
}int main()
sortedge(edge, m);
printf("%d", kruskal(edge, n, m));
return 0;
}
注意:每次新加入邊時,需注意不能出現迴路。 PTA7 10 公路村村通
如下 現有村落間道路的統計資料表中,列出了有可能建設成標準公路的若干條道路的成本,求使每個村落都有公路連通所需要的最低成本。輸入資料報括城鎮數目正整數n 1000 和候選道路數目m 3n 隨後的m行對應m條道路,每行給出3個正整數,分別是該條道路直接連通的兩個城鎮的編號以及該道路改建的預算成本。為簡...
7 10 公路村村通 30 分
現有村落間道路的統計資料表中,列出了有可能建設成標準公路的若干條道路的成本,求使每個村落都有公路連通所需要的最低成本。輸入資料報括城鎮數目正整數n 1000 和候選道路數目m 3n 隨後的m行對應m條道路,每行給出3個正整數,分別是該條道路直接連通的兩個城鎮的編號以及該道路改建的預算成本。為簡單起見...
7 10 公路村村通
通過的 以及注釋,注釋最多的地方,是思考的最多的地方 include include includeusing namespace std define n 1005 下次不要用n來命名,不然容易和下面的n弄混,unnecessarily int f n 樹的母節點,例如節點1的母節點f 1 2,那...