并查集

普通并查集

格子游戏

题目描述
image

参考题解

#include <iostream>
#include <cstdio>

using namespace std;

const int N = 4e4+5;

int n, m;

int p[N];

int find(int x)
{
    if(x != p[x])   p[x] = find(p[x]);
    return p[x];
}

int get(int x, int y)
{
    return x*n+y;
}

int main()
{
    cin >> n >> m;
    for(int i = 0; i < N; ++ i) p[i] = i;
    int ans = 0;
    for(int step = 1; step <= m; ++ step)
    {
        int x, y;
        scanf("%d%d", &x, &y);
        x -= 1, y -= 1; 
        char op[2];
        scanf("%s", op);
        if(ans > 0) continue;
        int a, b;
        a = get(x, y);
        if(op[0] == 'D')
        {
            b = get(x+1, y);
        }
        else
        {
            b = get(x, y+1);
        }
        a = find(a), b = find(b);
        if(a == b)
        {
            ans = step;
        }
        p[a] = b;
    }
    if(ans > 0)
    {
        printf("%d\n", ans);
    }
    else
    {
        cout << "draw" << endl;
    }
    return 0;
}

搭配购买

题目描述
image
image

参考题解

并查集+01背包

#include <iostream>
#include <cstdio>

using namespace std;

const int N = 1e4+5;

int n, m, w;

int p[N];
int cost[N], value[N];

int find(int x)
{
    if(x != p[x])   p[x] = find(p[x]);
    return p[x];
}

int dp[N];

int main()
{
    cin >> n >> m >> w;
    for(int i = 1; i <= n; ++ i)    p[i] = i;
    for(int i = 1; i <= n; ++ i)
    {
        scanf("%d%d", cost+i, value+i);
    }
    for(int i = 1; i <= m; ++ i)
    {
        int a, b;
        scanf("%d%d", &a, &b);
        int pa = find(a), pb = find(b);
        if(pa == pb)    continue;
        p[pa] = pb;
        cost[pb] += cost[pa];
        value[pb] += value[pa];
    }
    for(int i = 1; i <= n; ++ i)
    {
        if(p[i] == i)
        {
            for(int j = w; j >= cost[i]; -- j)
            {
                dp[j] = max(dp[j], dp[j-cost[i]] + value[i]);
            }
        }
    }
    cout << dp[w] << endl;
    return 0;
}

程序自动分析

题目描述
image
image

参考题解

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <unordered_map>

using namespace std;

const int N = 1e5+5, M = 2*N;

int n;

int p[M];

int find(int x)
{
    if(x != p[x])   p[x] = find(p[x]);
    return p[x];
}

unordered_map<int, int> ha;
int m = 0;
//离散化
int get(int x)
{
    if(!ha.count(x))    ha[x] = m++;
    return ha[x];
}

struct Query
{
    int a, b;
    int type;
    bool operator<(const Query& t) const
    {
        return type >= t.type;
    }
}query[N];

int main()
{
    int t;
    cin >> t;
    while(t --)
    {
        ha.clear();
        cin >> n;
        m = 0;
        for(int i = 0; i < n; ++ i)
        {
            int a, b, c;
            scanf("%d%d%d", &a, &b, &c);
            query[i] = {get(a), get(b), c};
        }
        for(int i = 0; i < m; ++ i)    p[i] = i;
        for(int i = 0; i < n; ++ i)
        {
            if(query[i].type == 1)
            {
                int pa = find(query[i].a), pb = find(query[i].b);
                p[pa] = pb;
            }
        }
        bool ans = true;
        for(int i = 0; i < n; ++ i)
        {
            if(query[i].type == 0)
            {
                int pa = find(query[i].a), pb = find(query[i].b);
                if(pa == pb)
                {
                    ans = false;
                    break;
                }
            }
        }
        if(ans) puts("YES");
        else    puts("NO");
    }
    return 0;
}

带权并查集

银河英雄传说

题目描述
image
image

参考题解

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <deque>
#include <string>
#include <unordered_map>

using namespace std;

const int INF = 0x3f3f3f3f, N = 3e4+5;

typedef long long LL;

int n;

int p[N], s[N], d[N];

int find(int x)
{
    if(x != p[x])
    {
        int root = find(p[x]);
        d[x] += d[p[x]];
        p[x] = root;
    }
    return p[x];
}

int main()
{
    for(int i = 1; i < N; ++ i)
    {
        p[i] = i;
        s[i] = 1;
    }
    int T;
    cin >> T;
    while(T --)
    {
        char op[2];
        int a, b;
        scanf("%s%d%d", op, &a, &b);
        int pa = find(a), pb = find(b);
        if(op[0] == 'M')
        {
            if(pa != pb)
            {
                d[pa] = s[pb];
                s[pb] += s[pa];
                p[pa] = pb;
            }
        }
        else
        {
            if(pa == pb)
            {
                cout << max(abs(d[a]-d[b])-1, 0) << endl;
            }
            else
            {
                cout << "-1" << endl;
            }
        }
    }
    return 0;
}

posted @ 2021-05-15 15:23  chaosliang  阅读(33)  评论(0)    收藏  举报