http://poj.org/problem?id=3723
这题虽然简单,但是还是错了很多次。
因为这题构建的图可能是不连通的。也就是说可能有很多棵树。
所以我以前写的并查集用在这上面会出问题的。
while(x != f[x])
x = f[x];
return f[x];
//我这样子每次用完之后并没有更新f[x]的值。
//虽然在连通图中没问题,但是在不连通的图里用就会有问题啦。
血的教训。。。。
改正:
if(x !=f[x])
f[x] = find(f[x]);
return f[x];
//============================================
code:
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn = 20050;
const int maxm = 50050;
struct edge {
int x, y, w;
bool operator < (const edge& rhs) const {
return w > rhs.w;
}
};
edge es[maxm];
int f[maxn];
int n, m;
int Find(int x)
{
if(x !=f[x])
f[x] = Find(f[x]);
return f[x];
}
int kruskal() {
int i, a, b;
int ans = 10000*n;
for(i=0; i<=n; ++i) f[i] = i;
sort(es, es+m);
for(i=0; i<m; ++i) {
a = Find(es[i].x);
b = Find(es[i].y);
if(a!=b) {
f[a] = b;
ans -= es[i].w;
}
}
return ans;
}
int main() {
int N, M, R, i, t;
scanf("%d",&t);
while(t--) {
scanf("%d%d%d",&N,&M,&R);
n = N+M;
m = R;
for(i=0; i<m; ++i) {
scanf("%d%d%d",&es[i].x, &es[i].y, &es[i].w);
es[i].y += N;
}
printf("%d\n", kruskal());
}
return 0;
}
Prim
int Prim()
{
int i, j, p, ans, minc;
memset(v, 0, sizeof v );
for(i=0; i<=n; ++i) dis[i] = inf;
dis[1] = 0;
ans = 0;
for(i=1; i<=n; ++i)
{
minc = inf, p = -1;
for(j=1; j<=n; ++j) if(!v[j])
if(minc>dis[j]) minc = dis[p=j];
if(-1==p) break;
v[p] = 1;
ans += minc;
for(j=0; j<G[p].size(); ++j)
{
pto &u = G[p][j];
if(!v[u.to] && dis[u.to] > u.len)
{
dis[u.to] =u.len;
}
}
}
if(i==n+1)
return ans;
else
return -1;
}
本文详细阐述了并查集在处理构建不连通图时的问题,通过实例展示了错误使用可能导致的问题,并给出了正确的实现方式。通过具体的代码实现,深入浅出地介绍了如何在不连通的图中正确应用并查集,避免常见的陷阱。

578

被折叠的 条评论
为什么被折叠?



