- 题解
prim 和 kruskal
- @ 2025-8-28 9:42:54
#include<bits/stdc++.h>
using namespace std;
const int N = 510;
int g[N][N];
int dist[N], st[N], pre[N];
int n, m;
void prim()
{
memset(dist, 0x3f, sizeof dist);
int res = 0;
dist[1] = 0;
for(int i = 0; i < n; i++)
{
int x = -1;
for(int j = 1; j <= n; j++)
{
if(!st[j] && (x == -1 || dist[j] < dist[x]))
x = j;
}
if(dist[x] == 0x3f3f3f3f)
{
cout << "impossible";
return;
}
st[x] = 1;
res += dist[x];
for(int j = 1; j <= n; j++)
{
if(dist[j] > g[x][j] && !st[j])
{
dist[j] = g[x][j];
pre[j] = x;
}
}
}
cout << res;
}
void getPath()
{
for(int i = n; i > 1; i--)
{
cout << i << " " << pre[i] << " " << endl;
}
}
int main()
{
memset(g, 0x3f, sizeof g);
cin >> n >> m;
while(m --)
{
int a, b, c;
cin >> a >> b >> c;
g[a][b] = g[b][a] = min(g[a][b], c);
}
prim();
//getPath();
return 0;
}
/*
每次将离连通部分最近的点和点对应的边加入到连通部分.
*/
#include<bits/stdc++.h>
using namespace std;
const int N = 1e5 + 10, M = 2e5 + 10, INF = 0x3f3f3f3f;
int n, m;
int fa[N];
struct Edge{
int a, b, w;
bool operator < (const Edge &W) const{
return w < W.w;
}
}g[M];
int find(int x)
{
if(fa[x] == x) return fa[x];
return fa[x] = find(fa[x]);
}
int kruskal()
{
sort(g, g + m);
for(int i = 1; i <= n; i++) fa[i] = i;
int res = 0, cnt = 0;
for(int i = 0; i < m; i++)
{
int a = g[i].a, b = g[i].b, w = g[i].w;
a = find(a), b = find(b);
if(a != b)
{
fa[a] = b;
res += w;
cnt ++;
}
}
if(cnt < n - 1) return INF;
return res;
}
int main()
{
cin >> n >> m;
for(int i = 0; i < m; i++)
{
int a, b, c;
cin >> a >> b >> c;
g[i] = {a, b, c};
}
int t = kruskal();
if(t == INF) cout << "impossible";
else cout << t;
return 0;
}
/*
原理:按照所有边的权值从小到大排序,一一枚举。
如果选择的这个边和之前选择所有边不构成回路,就选,否则,舍去。
直到选择了n-1条边为止。
回路: 边连接两个点已经连通了。 并查集判断所选边的两个点是否已经在同一个连通块
*/
0 条评论
目前还没有评论...