OJ 1428. Minimum Spanning Tree
题目描述
给定一张 n个点,m条边的有权无向连通图,求最小生成树的边权和。
Input
请从 stdin 读入。
输入第一行为两个正整数
n
,
m
n, m
n,m
(
1
≤
n
≤
5000
,
1
≤
m
≤
2
×
1
0
5
)
(1≤n≤5000,1≤m≤2×10^5)
(1≤n≤5000,1≤m≤2×105)。
接下来 m 行,第 i 行为用空格隔开的整数
u
i
u_i
ui,
v
i
v_i
vi,
w
i
w_i
wi (
1
≤
u
i
,
v
i
≤
n
,
1
≤
w
i
≤
10000
1 \leq u_i, v_i \leq n, 1 \leq w_i \leq 10000
1≤ui,vi≤n,1≤wi≤10000),表示第 i条边为从
u
i
u_i
ui到
v
i
v_i
vi 。
输入可能存在重边与自环。
Output
请输出到 stdout 中。
输出一行,包含一个整数,表示你的答案。
Sample Input
4 4
1 2 1
2 3 2
3 4 3
4 1 4
3 3
1 2 3
2 3 1
3 1 2
Sample Output
6
3
Constraints
Time Limit: 1s
Memory Limit: 128MB
Solution
采用无优化的 Prim算法求解最小生成树。无优化刚好能过,时间复杂度O(
∣
V
∣
2
+
∣
E
∣
|V|^2+|E|
∣V∣2+∣E∣)。
进一步可以采用heap优化,时间复杂度O[
(
∣
V
∣
+
∣
E
∣
)
log
∣
V
∣
(|V|+|E|)\log|V|
(∣V∣+∣E∣)log∣V∣]。如果采用Fabonacci heap优化,时间复杂度为O
(
∣
E
∣
+
∣
V
∣
log
∣
V
∣
)
(|E|+|V|\log|V|)
(∣E∣+∣V∣log∣V∣)。
Code
#include<iostream>
#include<algorithm>
#include<vector>
using namespace std;
struct edge{
int to;
int weight;
edge(int v, int w){
to=v;
weight=w;
}
};
vector<bool> visited;
vector<int> cost;
vector<vector<edge>> g;
int prim(){
int ans=0;
visited[1]=true;
cost[1]=0;
for(int i=0;i<g[1].size();i++){
int v=g[1][i].to;
cost[v]=g[1][i].weight;
}
bool flag=true;
while(flag){
flag=false;
int min_cost=100000;
int min_index=1;
for(int i=1;i<cost.size();i++){
if(visited[i]){
continue;
}
if(cost[i]<min_cost){
flag=true;
min_cost=cost[i];
min_index=i;
}
}
if(flag){
visited[min_index]=true;
ans+=min_cost;
for(int i=0;i<g[min_index].size();i++){
int v=g[min_index][i].to;
if(!visited[v]){
cost[v]=min(cost[v],g[min_index][i].weight);
}
}
}
}
return ans;
}
int main()
{
int n, m;
cin>>n>>m;
visited.assign(n+1,false);
g.assign(n+1,vector<edge>());
cost.assign(n+1,100000000);
int u, v, w;
for(int i=0;i<m;i++){
cin>>u>>v>>w;
if(u==v){
continue;
}
else{//重边选小的
bool flag1 = false;
for(int i=0;i<g[u].size();i++){
if(g[u][i].to==v){
if(g[u][i].weight>w){
g[u][i].weight=w;
}
flag1 = true;
break;
}
}
if(flag1==false){
edge e1(v,w);
g[u].push_back(e1);
}
bool flag2 = false;
for(int i=0;i<g[v].size();i++){
if(g[v][i].to==u){
if(g[v][i].weight>w){
g[v][i].weight=w;
}
flag2 = true;
break;
}
}
if(flag2==false){
edge e2(u,w);
g[v].push_back(e2);
}
}
}
cout<<prim();
return 0;
}