hihoCoder1097
暴力法 ( O ( l o g ( n 2 ) O(log(n^2) O(log(n2))
#include <iostream>
#include <cstring>
using namespace std;
const int INF = 0x3f3f3f3f;
bool st[10005];
int dist[10005];
int g[1010][10005];
int n;
int prim() {
int res = 0;
for (int i = 1; i <= n; i++) {
dist[i] = INF;
st[i] = false;
}
dist[1] = 0;
for (int i = 1; i <= n; i++) {
int id = -1, min_dist = INF;
for (int j = 1; j <= n; j++) {
if (!st[j] && dist[j] < min_dist) {
id = j;
min_dist = dist[j];
}
}
st[id] = true;
res += dist[id];
//刷新辅助数组
for (int j = 1; j <= n; j++) {
if (!st[j] && dist[j] > g[id][j]) {
dist[j] = g[id][j];
//dist[j] = min(dist[j], g[id][j]);
}
}
}
return res;
}
int main() {
cin >> n;
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= n; j++) {
cin >> g[i][j];
}
}
memset(dist, 0, sizeof dist);
cout << prim() << endl;
return 0;
}
优先队列(堆优化) O ( ( n + m ) l o g m ) O((n + m)logm) O((n+m)logm)
#include <iostream>
#include <cstring>
#include <queue>
using namespace std;
const int maxn = 1005;
const int INF = 0x7fffffff;
int vis[maxn];//判断是否标记
int p[maxn][maxn];//存图
int n, m, ans = 0;
struct edge { //保存边的情况,to为通往的边
int to;
int v; //权值
friend bool operator < (const edge &x, const edge &y) {
return x.v > y.v; //优先队列即最小堆
}
}now;
priority_queue <edge> q;
void prim (int key) {
vis[key] = 1; //标记起始点
while (!q.empty()) q.pop();
for (int i = 0; i < n - 1; i++) {
for (int j = 0; j < n; j++) { //记入新加入点的情况
if (!vis[j]) { //没标记过的点就加入
now.to = j;
now.v = p[key][j];
//printf("j=%d,p[%d][%d]=%d\n",j,key,j,p[key][j]);
q.push(now);
}
}
while (!q.empty() && vis[q.top().to]) {
q.pop();
}
if (q.empty()) break;
now = q.top();
key = now.to;
ans += now.v; //累加最小边的权值
vis[key] = 1;
q.pop();
}
}
int main() {
//cin >> n;
scanf ("%d", &n);
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
cin >> p[i][j];
}
}
memset(vis, 0, sizeof vis);
prim(0);
cout << ans << endl;
return 0;
}