poj1182和ural1003

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);
    }
}


你可能感兴趣的:(poj1182和ural1003)