HDU - 3038 种类并查集
2017-03-28 14:38
211 查看
思路:种类并查集的每个节点应该保存它的父节点以及他和父节点之间的关系。假设root表示根结点,sum[i-1]表示i到根结点的和,那么sum[j-1] - sum[i]可以得到区间[j, i]的和。那么给定(x, y, real)可以看作x-1到节点y的和为real
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 = 200000 + 5;
struct node{
int par;
int real;
}a[maxn];
int find(int x, int &root) {
if(a[x].par == x) {
root = x;
return a[x].real;
}
int r = a[x].real + find(a[x].par, root);
//路径压缩
a[x].par = root;
return a[x].real = r;
}
bool unionset(int x, int y, int real) {
int r1, r2;
int rx = find(x, r1), ry = find(y, r2);
if(r1 == r2) {
if(rx - ry != real) return false;
}
else { //合并
a[r1].par = y;
a[r1].real = real - rx;
}
return true;
}
int main() {
int n, m;
while(scanf("%d%d", &n, &m) == 2) {
for(int i = 0; i <= n; ++i) {
a[i].par = i;
a[i].real = 0;
}
int x, y, r, ans = 0;
for(int i = 0; i < m; ++i) {
scanf("%d%d%d", &x, &y, &r);
if(!unionset(x-1, y, r)) ans++;
}
printf("%d\n", 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 = 200000 + 5;
struct node{
int par;
int real;
}a[maxn];
int find(int x, int &root) {
if(a[x].par == x) {
root = x;
return a[x].real;
}
int r = a[x].real + find(a[x].par, root);
//路径压缩
a[x].par = root;
return a[x].real = r;
}
bool unionset(int x, int y, int real) {
int r1, r2;
int rx = find(x, r1), ry = find(y, r2);
if(r1 == r2) {
if(rx - ry != real) return false;
}
else { //合并
a[r1].par = y;
a[r1].real = real - rx;
}
return true;
}
int main() {
int n, m;
while(scanf("%d%d", &n, &m) == 2) {
for(int i = 0; i <= n; ++i) {
a[i].par = i;
a[i].real = 0;
}
int x, y, r, ans = 0;
for(int i = 0; i < m; ++i) {
scanf("%d%d%d", &x, &y, &r);
if(!unionset(x-1, y, r)) ans++;
}
printf("%d\n", ans);
}
return 0;
}
如有不当那个之处欢迎指出!
相关文章推荐
- 类似区间计数的种类并查集两题--HDU 3038 & POJ 1733
- hdu 3038(种类并查集)
- hdu 3038 How Many Answers Are Wrong (种类并查集)
- hdu 3038(How Many Answers Are Wrong)+3047(Zjnu Stadium)(种类并查集)
- hdu 3038 How Many Answers Are Wrong(种类并查集)2009 Multi-University Training Contest 13
- hdu 3038 种类并查集How Many Answers Are Wrong
- HDU 3038 How Many Answers Are Wrong(种类并查集)
- 类似区间计数的种类并查集两题--HDU 3038 &amp; POJ 1733
- HDU 3038 How Many Answers Are Wrong(并查集)
- hdu 1829 种类并查集
- hdu 3038 How Many Answers Are Wrong【并查集的简单应用】
- 数据结构 种类并查集 HDU 1829
- hdu 3038 How Many Answers Are Wrong (带权并查集入门)
- HDU - 3038(并查集)How Many Answers Are Wrong
- hdu 3038 How Many Answers Are Wrong(带权并查集)
- 带权并查集 - HDU 3038
- D - How Many Answers Are Wrong HDU - 3038 【关系并查集】
- 【并查集】HDU_3038_How Many Answers Are Wrong
- D - How Many Answers Are Wrong HDU - 3038(带权并查集)
- HDU 3038 How Many Answers Are Wrong (并查集)