今天写了两道并查集的题目,感觉还好。
并查集可以用来判断树的根节点的个数,可以用来判断是否成环,最小生成树也可以用并查集实现。
hdu-1232 畅通工程 (并查集判断根节点个数)
http://acm.hdu.edu.cn/showproblem.php?pid=1232
// Contest: HDOJ
// URL: http://acm.hdu.edu.cn/showproblem.php?pid=1232
// Memory Limit: 65 MB
// Time Limit: 4000 ms
//
// Powered by CP Editor (https://cpeditor.org)
#include <bits/stdc++.h>
using namespace std;
int n, m;
int f[1005];
int find(int a)
{
while (a != f[a])
{
a = f[a];
}
return a;
}
void merge(int a, int b)
{
if (find(a) == find(b))
return;
int la = find(a);
int lb = find(b);
f[la] = lb;
return;
}
int main()
{
while (cin >> n >> m, n)
{
for (int i = 1; i <= n; i++)
{
f[i] = i;
}
for (int i = 1; i <= m; i++)
{
int a, b;
cin >> a >> b;
merge(a, b);
}
int cnt = 0;
for (int i = 1; i <= n; i++)
{
if (i == f[i])
cnt++;
}
printf("%d\n", cnt - 1);
}
}
hdu-1272 小希的迷宫 (并查集判环)
http://acm.hdu.edu.cn/showproblem.php?pid=1272
这题主要就是不能成环,并且只能有一颗树。
判断成不成环就是在合并的时候判断一下是不是同一棵树,是的话合并就会成环。
还有就是这题不知道有什么坑点,我现在还没有写出来啊(QAQ——思路明明挺简单的)
wa了很多次以后终于发现是 0 0是合法的,真坑啊
附上ac代码:
// Problem: 小希的迷宫 // Contest: HDOJ // URL: http://acm.hdu.edu.cn/showproblem.php?pid=1272 // Memory Limit: 65 MB // Time Limit: 2000 ms // // Powered by CP Editor (https://cpeditor.org) #include <bits/stdc++.h> using namespace std; int f[100005]; int vis[100005]; void init() { for (int i = 1; i <= 100005; i++) { f[i] = i; } memset(vis, 0, sizeof(vis)); } int find(int x) { int temp; temp = x; while (f[x] != x) x = f[x]; if (f[temp] != x) //路径压缩 f[temp] = x; //直接把节点指向根节点,优化后续查找 return x; } void merge(int a, int b) { int la = find(a); int lb = find(b); if (la != lb) { f[la] = lb; } } int main() { int n, m; init(); while (cin >> n >> m, n != -1 && m != -1) { int flag = 1; if (n == 0 & m == 0) { flag = 1; init(); printf("Yes\n"); } else { vis[n] = 1; vis[m] = 1; if (find(n) == find(m)) { flag = 0; merge(m, n); } else { merge(m, n); } while (cin >> n >> m, n + m) { vis[n] = 1; vis[m] = 1; if (find(n) == find(m)) { flag = 0; } else { merge(m, n); } } if (flag == 1) { int count = 0; for (int i = 1; i <= 100005; i++) { if (i == f[i] && vis[i] != 0) { count++; } } // printf("%d\n",count); if (count == 1) printf("Yes\n"); else printf("No\n"); } else printf("No\n"); flag = 1; init(); } } }