nyoj 1022 合纵连横 经典并查集
2017-03-25 12:22
260 查看
思路:关键在于并查集的删点操作。 给每个诸侯国一个另外的编号,比如box[i]表示诸侯国i现在处于第box[i]个联盟,可以随时改变它的联盟编号,并且让box[i] = k, 实现删除操作。以前联盟中的那个点是一个虚点,只是帮助子节点找到根结点。查找时通过联盟编号查询。
AC代码
#include <cstdio>
#include <cmath>
#include <cctype>
#include <algorithm>
#include <cstring>
#include <utility>
#include <string>
#include <iostream>
#include <map>
#include <set>
#include <vector>
#include <queue>
#include <stack>
using namespace std;
#pragma comment(linker, "/STACK:1024000000,1024000000")
#define eps 1e-10
#define inf 0x3f3f3f3f
#define PI pair<int, int>
typedef long long LL;
const int maxn = 100000 + 5;
int p[maxn<<1], box[maxn], vis[maxn<<1];
int find(int x) {
return p[x] == x ? x : p[x] = find(p[x]);
}
void unionset(int x, int y) {
int px = find(box[x]), py = find(box[y]);
if(px != py) p[px] = py;
}
int cur;
void del(int x) { //删点
box[x] = cur++;
p[box[x]] = box[x];
}
int main() {
int n, m, kase = 1;
while(scanf("%d%d", &n, &m) == 2) {
cur = n;
for(int i = 0; i < n; ++i) {
p[i] = i;
box[i] = i;
}
int x, y;
char ch;
for(int i = 0; i < m; ++i) {
getchar();
scanf("%c", &ch);
if(ch == 'U') {
scanf("%d%d", &x, &y);
unionset(x, y);
}
else {
scanf("%d", &x);
del(x);
}
}
memset(vis, 0, sizeof(vis));
for(int i = 0; i < n; ++i) {
vis[find(box[i])] = 1;
}
int ans = 0;
for(int i = 0; i < cur; ++i) {
if(vis[i]) ++ans;
}
printf("Case #%d: %d\n", kase++, ans);
}
return 0;
}
如有不当之处欢迎指出!
AC代码
#include <cstdio>
#include <cmath>
#include <cctype>
#include <algorithm>
#include <cstring>
#include <utility>
#include <string>
#include <iostream>
#include <map>
#include <set>
#include <vector>
#include <queue>
#include <stack>
using namespace std;
#pragma comment(linker, "/STACK:1024000000,1024000000")
#define eps 1e-10
#define inf 0x3f3f3f3f
#define PI pair<int, int>
typedef long long LL;
const int maxn = 100000 + 5;
int p[maxn<<1], box[maxn], vis[maxn<<1];
int find(int x) {
return p[x] == x ? x : p[x] = find(p[x]);
}
void unionset(int x, int y) {
int px = find(box[x]), py = find(box[y]);
if(px != py) p[px] = py;
}
int cur;
void del(int x) { //删点
box[x] = cur++;
p[box[x]] = box[x];
}
int main() {
int n, m, kase = 1;
while(scanf("%d%d", &n, &m) == 2) {
cur = n;
for(int i = 0; i < n; ++i) {
p[i] = i;
box[i] = i;
}
int x, y;
char ch;
for(int i = 0; i < m; ++i) {
getchar();
scanf("%c", &ch);
if(ch == 'U') {
scanf("%d%d", &x, &y);
unionset(x, y);
}
else {
scanf("%d", &x);
del(x);
}
}
memset(vis, 0, sizeof(vis));
for(int i = 0; i < n; ++i) {
vis[find(box[i])] = 1;
}
int ans = 0;
for(int i = 0; i < cur; ++i) {
if(vis[i]) ++ans;
}
printf("Case #%d: %d\n", kase++, ans);
}
return 0;
}
如有不当之处欢迎指出!
相关文章推荐
- nyoj 1022 合纵连横(经典并查集=---删点操作)
- NYOJ1022合纵连横(支持删除操作的并查集)
- NYOJ 1022--合纵连横 【并查集删点】
- NYOJ-1022合纵连横【并查集删除算法】
- NYOJ-1022合纵连横【并查集删除算法】
- nyoj1022 合纵连横 ---支持合并,删除,查找的并查集
- nyoj1022合纵连横(带分离操作的并查集)
- NYOJ 1022 合纵连横(并查集删点)
- nyoj 1022:合纵连横(并查集删点)
- NYOJ-1022合纵连横(并查集的删除操作)
- NYOJ_1022 合纵连横 并查集的删除
- nyoj 1022 合纵连横 【并查集的删除】
- 【NYOJ 1022】合纵连横 【并查集的 并查删操作】
- nyoj 1022 合纵连横【并查集节点的删除】
- NYOJ 合纵连横(并查集删点)
- NYOJ 题目1022合纵连横
- 并查集之找假爹(并查集删除操作)-NYOJ-合纵连横
- NYOJ合纵连横【并查集的合并和删除】
- 1022 合纵连横【并查集 元素的删除】
- NYOJ_1022_合纵连横