題目
題目輸入爲一個圖的鄰接矩陣,求圖的最小生成樹中最長邊的權值。
直接用Prim算法解決,詳細原理可以參考我的這篇博客
假設是連通網,是上最小生成樹的邊集合,Prim算法將圖中所有頂點分爲兩類,一類爲集合,該集合中的點表示該點已經被選取爲生成樹上的一個點,另一類爲集合,表示還未被選取爲生成樹中的點,其中爲圖中所有點的集合。算法可以選取集合中的任意一個頂點初始化集合,即。考慮集合與集合中相連的各條邊,選取其中權值最小的那一條邊,其中爲圖中的邊集,將點加入集合,邊併入集合,重複上訴過程直至爲止。此時中必有條邊,則爲的最小生成樹。
Prim
#include "iostream"
#include "vector"
#include "climits"
#include "algorithm"
using namespace std;
const int INF = INT_MAX;
int N;
int slove(vector<vector<int> > &map){
vector<int> U;//最小生成樹中的點集合
vector<int> V;//除了U中剩餘的點集合
for (int i = 1; i < N;i++)
V.push_back(i);
U.push_back(0); //起始把0號點加入集合U
int Max = -1;
while(U.size()!=N){
int Min = INF;
int u, v;
for (vector<int>::iterator i = U.begin(); i != U.end();i++)
{
for (vector<int>::iterator j = V.begin(); j != V.end();j++)
{
if(map[*i][*j]<Min){
Min = map[*i][*j];
u = *i;
v = *j;
}
}
}
if(map[u][v]>Max)
Max = map[u][v];
U.push_back(v);
vector<int>::iterator iter = find(V.begin(), V.end(), v);
V.erase(iter);
}
return Max;
}
int main(){
int T;
cin >> T;
while(T--){
cin >> N;
vector<vector<int>> map(N, vector<int>(N, 0));
for (int i = 0; i < N;i++){
for (int j = 0; j < N;j++){
cin >> map[i][j];
}
}
cout << slove(map) << endl;
}
//system("pause");
return 0;
}
kruskal(有點慢。。。)
#include "iostream"
#include "vector"
#include "climits"
#include "algorithm"
#include "cstring"
using namespace std;
const int INF = INT_MAX;
int N;
int parent[510];
typedef struct{
int x, y,w;
} Edge;
bool cmp(Edge a, Edge b){
return a.w < b.w;
}
int find_root(int x){
if(parent[x]==x){
return x;
}
else
{
return parent[x] = find_root(parent[x]);
}
}
int Union(int x, int y){
int x_root = find_root(x);
int y_root = find_root(y);
if(x_root==y_root)
return 0;//在同一個集合,合併失敗
else
{
parent[x_root] = y_root;//簡單的將y_root作爲父節點
return 1;//合併成功
}
}
int kruscal(vector<Edge> &edges)
{
int Max = INT_MIN;
for (int i = 0; i < edges.size();i++){//edges已經按權值排好序
int x = edges[i].x;
int y = edges[i].y;
if(Union(x, y)){//x,y不再一個連通分量中
if(edges[i].w>Max){
Max = edges[i].w;
}
}
}
return Max;
}
int main(){
int T;
cin >> T;
while(T--){
for (int i = 0; i < 510;i++){//初始化parent數組
parent[i] = i;
}
cin >> N;
vector<Edge> edges;
for (int i = 0; i < N;i++){//輸入數據
for (int j = 0; j < N;j++){
int t;
cin >> t;
if(t!=0){
Edge e;
e.x = i;
e.y = j;
e.w = t;
edges.push_back(e);
}
}
}
sort(edges.begin(), edges.end(), cmp);
cout << kruscal(edges) << endl;
}
//system("pause");
return 0;
}