【注】codeup不是单点测试!!!
- 思路1: Prim算法
#include <bits/stdc++.h>
using namespace std;
const int maxn = 110, INF = 0x3fffffff;
int d[maxn], G[maxn][maxn];
bool vis[maxn];
int Prim(int start, int n)
{
fill(d, d + maxn, INF);
memset(vis, false, sizeof(vis));
d[start] = 0;
int ans = 0;
for(int i = 0; i < n; ++i)
{
int mid = -1, Min = INF;
for(int j = 1; j <= n; ++j)
{
if(vis[j] == false && d[j] < Min)
{
Min = d[j];
mid = j;
}
}
if(mid == -1) return -1;
vis[mid] = true;
ans += d[mid];
for(int j = 1; j <= n; ++j)
{
if(vis[j] == false && G[mid][j] < d[j])
{
d[j] = G[mid][j];
}
}
}
return ans;
}
int main()
{
int n;
while(scanf("%d", &n) != EOF)
{
if(n == 0) break;
int N = n * (n - 1) / 2;
fill(G[0], G[0] + maxn * maxn, INF);
for(int i = 0; i < N; ++i)
{
int c1, c2, len;
scanf("%d %d %d", &c1, &c2, &len);
G[c1][c2] = G[c2][c1] = len;
}
printf("%d\n", Prim(1, n));
}
return 0;
}
- 思路2: Prim+堆优化
#include <bits/stdc++.h>
using namespace std;
const int maxn = 110, INF = 0x3fffffff;
int d[maxn], G[maxn][maxn];
bool vis[maxn];
struct node
{
int id, d;
bool operator < (const node & tmp) const { return d > tmp.d; }
};
int Prim(int start, int n)
{
fill(d, d + maxn, INF);
memset(vis, false, sizeof(vis));
d[start] = 0;
priority_queue<node> q;
q.push(node{start, 0});
int ans = 0;
while(!q.empty())
{
node now = q.top();
q.pop();
if(vis[now.id]) continue;
vis[now.id] = true;
ans += d[now.id];
for(int i = 1; i <= n; ++i)
{
if(vis[i] == false && G[now.id][i] != INF)
{
if(G[now.id][i] < d[i])
{
d[i] = G[now.id][i];
q.push(node{i, d[i]});
}
}
}
}
return ans;
}
int main()
{
int n;
while(scanf("%d", &n) != EOF)
{
if(n == 0) break;
int N = n * (n - 1) / 2;
fill(G[0], G[0] + maxn * maxn, INF);
for(int i = 0; i < N; ++i)
{
int c1, c2, len;
scanf("%d %d %d", &c1, &c2, &len);
G[c1][c2] = G[c2][c1] = len;
}
printf("%d\n", Prim(1, n));
}
return 0;
}
- 思路3: Kruskal
#include <bits/stdc++.h>
using namespace std;
const int maxn = 110;
struct edge
{
int v1, v2, len;
};
int father[maxn];
void Init(int n) { for(int i = 0; i <= maxn; ++i) father[i] = i;}
int FindRoot(int x)
{
int tmp = x;
while(father[x] != x)
{
x = father[x];
}
while(father[tmp] != tmp)
{
int tmp2 = tmp;
tmp = father[tmp];
father[tmp2] = x;
}
return x;
}
bool cmp(edge a, edge b) { return a.len < b.len; }
int Kruskal(int nv, int ne, vector<edge> & ans)
{
Init(nv);
int sum = 0, numE = 0;
sort(ans.begin(), ans.end(), cmp);
for(int i = 0; i < ne; ++i)
{
int ra = FindRoot(ans[i].v1), rb = FindRoot(ans[i].v2);
if(ra != rb)
{
father[ra] = rb;
sum += ans[i].len;
numE++;
if(numE == nv-1) break;
}
}
if(numE != nv-1) return -1;
else return sum;
}
int main()
{
int n;
while(scanf("%d", &n) != EOF)
{
if(n == 0) break;
int N = n * (n - 1) / 2;
vector<edge> ans;
for(int i = 0; i < N; ++i)
{
int c1, c2, len;
scanf("%d %d %d", &c1, &c2, &len);
ans.push_back(edge{c1, c2, len});
}
printf("%d\n", Kruskal(n, N, ans));
}
return 0;
}
- 思路 4 Kruskal + 堆优化 这题属于边稠密图,正常sort的话可能会超时, 故用堆优化
#include <bits/stdc++.h>
using namespace std;
const int maxn = 110;
struct edge
{
int v1, v2, len;
bool operator < (const edge & tmp) const { return len > tmp.len; }
};
int father[maxn];
void Init(int n) { for(int i = 0; i <= maxn; ++i) father[i] = i;}
int FindRoot(int x)
{
int tmp = x;
while(father[x] != x)
{
x = father[x];
}
while(father[tmp] != tmp)
{
int tmp2 = tmp;
tmp = father[tmp];
father[tmp2] = x;
}
return x;
}
int Kruskal(int nv, int ne, priority_queue<edge> & pq)
{
Init(nv);
int sum = 0, numE = 0;
while(!pq.empty())
{
edge now = pq.top();
pq.pop();
int ra = FindRoot(now.v1), rb = FindRoot(now.v2);
if(ra != rb)
{
numE++;
sum += now.len;
father[ra] = rb;
if(numE == nv-1) break;
}
}
if(numE != nv-1) return -1;
else return sum;
}
int main()
{
int n;
while(scanf("%d", &n) != EOF)
{
if(n == 0) break;
int N = n * (n - 1) / 2;
priority_queue<edge> q;
for(int i = 0; i < N; ++i)
{
int c1, c2, len;
scanf("%d %d %d", &c1, &c2, &len);
q.push(edge{c1, c2, len});
}
printf("%d\n", Kruskal(n, N, q));
}
return 0;
}