競技プログラミング プリム法編 [備忘録]
はじめに
制限時間内に問題を解く競技プログラミングにおいて、アルゴリズムを調べるために本を読み文字を打ち込むことはとてもめんどくさいと感じたため、ここにMain関数で呼び出して使える形で残しておくことでAtCoderでやるときにコピペで使えるようにしています。
下部ソースコードでは、最少全域木のコストを返している関数です。
また、AOJでacceptももらいました。AOJのURLは以下に貼っておきます。
最小全域木 | グラフ | Aizu Online Judge
プリム法特徴
最少全域木におけるコストの総和を求めている。
O(V*V)でV=10000程度は対応可能
プリム法そのものはここがわかりやすい。
ソースコード
#include<iostream>
#include<vector>
#include<algorithm>
#include<queue>
using namespace std;
#define MV 10000
#define INF 1e9
struct edge{int to,cost;};//辺の表現方法の1種
vector <edge> G[MV];
bool used[MV];//各点を一度使ったかどうか
int V,E;//Vは点、Eは辺の個数
int d[MV];//コストを格納している
int prim(){
for(int i = 0;i < V;i++){//初期化
d[i] = INF;
used[i] = false;
}
d[0] = 0;
used[0] = true;
for(int i = 0;i < G[0].size();i++)
d[G[0][i].to] = G[0][i].cost;
int num = 0;
for(int j = 0;j < V;j++){
int m = -1;
for(int i = 0;i < V;i++){
if(used[i] == false && (m == -1 || d[m] > d[i]))
m = i;
}
if (m == -1)
break;
used[m] = true;
num += d[m];
for(int i = 0;i < G[m].size();i++)
d[G[m][i].to] = min(d[G[m][i].to],G[m][i].cost);
}
return num;
}
int main(){
int first;
cin >> V >> E;
for(int i = 0;i < E;i++){
int f,t;
edge e;
cin >> f >> e.to >> e.cost;
G[f].push_back(e);
/*
G[f]にはfからでてる辺が格納されている。
*/
t = e.to;
e.to = f;
G[t].push_back(e);
}
int fl = prim();
cout << fl << endl;
}