并查集 - 2

>1 樱子的爱好

题目

https://codeforces.com/contest/2008/problem/D

思路

5 4 1 3 2
10011

为例
i = 1, p1 = 5, s5 = 1--> i = 5, p5 = 2, s2 = 0 --> i = 2, p2 = 4, s4 = 1 --> i = 4, p4 = 3, s3 = 0 --> i = 3, p3 = 1, s1 = 1

无论i = 1还是5, 2, 4, 3,最终黑色的个数都一样,因为会重复这个过程,所以它们就在一根树枝上,可以把1看作根结点,后面的数字标记一下,表示已经操作过了,就能跳过,将它们的父亲都设为1, 最终遍历就直接输出父亲节点的黑色数量

代码

#include <iostream>
#include <vector>
#include <string>

using namespace std;

int main()
{
    int t;
    cin >> t;
    while (t--)
    {
        int n;
        cin >> n;
        vector<int> p(n+1, 0), a(n+1, 0), goal(n+1, 0), cnt(n+1, 0), nu(n+1, 0);
        for (int i = 1; i <= n; i++) cin >> p[i], a[i] = p[i];
        string s;
        cin >> s;
        for (int i = 0; i < n; i++)
        {
            if (s[i] == '0') nu[i + 1]++;
        }

        int count = 0;
        for (int i = 1; i <= n; i++)
        {
            if (!goal[i])
            {
                int num = p[i];
                cnt[i] += nu[num];
                goal[num] = 1;
                count++;
                int res = p[num];
                p[num] = i;
                while (num != i)
                {
                    num = res;
                    cnt[i] += nu[num];
                    goal[num] = 1;
                    count++;
                    res = p[num];
                    p[num] = i;
                }
                if (count == n) break;
            }
        }
        for (int i = 1; i <= n; i++) cout << cnt[p[a[i]]] << ' ';
        cout << endl;
    }
}

>2 小诚因为金铲铲D不到牌破产啦

题目

http://oj.whpu.tech:7788/problem/299

代码

#include <iostream>
#include <string>

using namespace std;
const int N = 2e5 + 10;
int p[N], a[N], b[N];

int findd(int x);
void uniona(int x, int y);
int main()
{
	int n, m; cin >> n >> m;
	for (int i = 1; i <= n; i++) cin >> a[i], p[i] = i;
	for (int i = 1; i <= n; i++) cin >> b[i];
	while (m--)
	{
		int x, y; cin >> x >> y;
		int p1 = findd(x), p2 = findd(y);
		if (p1 != p2) uniona(p1, p2);
	}
	for (int i = 1; i <= n; i++)
	{
		if (i == p[i])
		{
			if (a[i] != b[i])
			{
				cout << "No" << endl;
				return 0;
			}
		}
	}
	cout << "Yes" << endl;
}
int findd(int x)
{
	int a = x;
	while (a != p[a]) a = p[a];
	int b = x;
	while (b != a)
	{
		int c = p[b];
		p[b] = a;
		b = c;
	}
	return a;
}
void uniona(int x, int y)
{
	p[x] = y;
	a[y] += a[x];
	b[y] += b[x];
}
posted @ 2024-11-28 11:31  PeachyGalaxy  阅读(9)  评论(0编辑  收藏  举报