您的位置:首页 > 其它

poj1182和ural1003

2014-06-28 00:18 281 查看
poj1182

并查集的运用,集合之间的关系表示,增加一个字段来表示和跟的关系r[x]

如果r[x] == 0表示和根同类,r[x] == 1表示根吃x,r[x] == 2表示x吃根。

那么现在如果x,y的关系为r[y],y,z的关系为r[z],那么x和z的关系则是(r[y] + r[z]) % 3。不妨画个图看看。

现在读入一个陈述:

1.如果x,y在同一个集合里面:

1. 1 x y陈述x,y是同类,

那么根据他们与根的关系来判断,如果r[x] != r[y],则说明他们不是同类

2. 2 x y陈述x吃y,那么x与根的关系为r[x],y与根的关系为r[y],那么根与x的关系为3 - r[x],

所以y与x的关系为3 - r[x] + r[y],x吃y,则表示为 (3 - r[x] + r[y]) % 3 == 1。明显以x为根的话,y对x关系就是1.

如果x,y不在一个集合里面,则合并集合,

现在要修改根的关系。

首先father[x]和x的关系为r[x],x和y的关系为d - 1,那么father[x]和y的关系为 r[x] + d - 1;

father[y]和y的关系为r[y],那么y和father[y]的关系为3 - r[y],那么father[x]和father[y]的关系为 r[x] + d - 1 + 3 - r[y]。

更新r[father[y]]即可。

ural1003:

与poj1182类似。

i, j为偶,则说明i和j - 1的关系为同奇偶。

同理表示为不同奇偶。

r[x] == 0表示和根同奇偶,r[x] == 1表示和根不同奇偶。

那么关系更改就简单很多了比poj1182.

注意一点是,首先要离散化,离散化之后还要注意规定了一个长度,如果他说的大于这个长度很定是假的。

然后答案可能是0.

poj1182

AC代码

#include <cstdio>
#include <cstring>

const int maxn = 50007;

int father[maxn], r[maxn];

int find(int a) {
if (a == father[a]) {
return a;
}
else {
int t = father[a];
father[a] = find(father[a]);
r[a] = (r[a] + r[t]) % 3;
return father[a];
}
}

void union_set(int a, int b, int d) {
int x = find(a);
int y = find(b);
father[y] = x;
r[y] = (r[a] + d - 1 + 3 - r[b]) % 3;
}

int main() {
//    freopen("input.txt", "r", stdin);
int n, m;
int ans = 0;
scanf("%d%d", &n, &m);
for (int i = 1; i <= n; i++) {
father[i] = i;
r[i] = 0;
}
while (m--) {
int type, a, b;
scanf("%d%d%d", &type, &a, &b);
if (a > n || b > n || (type == 2 && a == b)) {
ans++;
continue;
}
int x = find(a);
int y = find(b);
if (x == y) {
if ((type == 1 && (r[a] != r[b]))) {
ans++;
}
else if (type == 2 && (3 - r[a] + r[b]) % 3 != 1) {
ans++;
}
}
else {
union_set(a, b, type);
}
}
printf("%d\n", ans);
return 0;
}


ural1003

#include <cstdio>
#include <cstring>
#include <map>
#include <algorithm>

using namespace std;
const int maxn = 5007;

struct Seg {
int left, right, type;
};
struct Seg seg[maxn];
int father[maxn], r[maxn], ar[maxn], length, cnt;
map<int, int> maps;

void init() {
length = 1;
for (int i = 2; i <= cnt; i++) {
if (ar[i] != ar[i - 1]) {
length++;
ar[length] = ar[i];
}
}
}

int find(int x) {
if (x == father[x]) {
return x;
}
else {
int t = father[x];
father[x] = find(father[x]);
r[x] = (r[x] + r[t]) % 2;
return father[x];
}
}

int binarySearch(int a) {
int low = 1;
int high = length;
while (low <= high) {
int mid = (low + high) >> 1;
if (ar[mid] == a) {
return mid;
}
else if (ar[mid] > a) {
high = mid - 1;
}
else {
low = mid + 1;
}
}
return -1;
}

void union_set(int a, int b, int type) {
int x = find(a);
int y = find(b);
father[y] = x;
r[y] = (r[a] + type + 2 - r[b]) % 2;
}
int main() {
//    freopen("input.txt", "r", stdin);
while (scanf("%d", &length) != EOF) {
if (length == -1) {
break;
}
int m;
scanf("%d", &m);
maps.clear();
cnt = 0;
int flag = 0;
int s_m = m;
for (int i = 1; i <= m; i++) {
int a, b;
char even[30];
scanf("%d%d%s", &a, &b, even);
if (!flag && (a > length || b > length)) {
flag = 1;
s_m = i - 1;
}
ar[++cnt] = a - 1;
ar[++cnt] = b;
seg[i].left = a - 1;
seg[i].right = b;
if (even[0] == 'e') {
seg[i].type = 0;
}
else {
seg[i].type = 1;
}
}
sort(ar + 1, ar + 1 + cnt);
init();
int ans = 0;
for (int i = 1; i <= length; i++) {
father[i] = i;
r[i] = 0;
}
for (int i = 1; i <= m && i <= s_m; i++) {
int left = binarySearch(seg[i].left);
int right = binarySearch(seg[i].right);
int x = find(left);
int y = find(right);
if (x == y) {
if (seg[i].type == 0 && r[left] != r[right]) {
break;
}
else if (seg[i].type == 1 && (r[left] + r[right]) != 1) {
break;
}
}
else {
union_set(left, right, seg[i].type);
}
ans = i;
}
printf("%d\n", ans);
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: