基础树上问题 P5836 [USACO19DEC]Milk Visits S【并查集进行图的染色】

题目

https://www.luogu.com.cn/problem/P5836

 

 分析

由于每个点的颜色选择范围都是两种,所以我们可以使用并查集来记录同一种颜色的连通块。

刚开始我的思路比较歪,只是单纯的考虑怎样能记录可以使朋友开心,后来想到可以考虑在怎样的情况下不能使朋友开心

具体看代码

代码

#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
using namespace std;
#define maxn 100010
#define maxm 100010
int father[maxn], answer[maxn],ranks[maxn];
char  mark[maxn];
int cnt = 0;
int n, m;
int find(int x)
{
    if (father[x] == x)
        return x;
     return father[x] = find(father[x]);
}
void merge(int x,int y)
{
    int a = find(x);
    int b = find(y);
    if (a == b)return;
    if (ranks[a] > ranks[b])father[b] = a;
    else
    {
        father[a] = b;
        if (ranks[a] == ranks[b])ranks[b]++;
    }
}

int main()
{
    cin >> n >> m;
    for (int i = 1; i <= n; i++)
    {
        cin >> mark[i];
        father[i] = i;
    }
    for (int i = 1; i <= n - 1; i++)
    {
        int a, b;
        cin >> a >> b;//这里是思路的核心
        if (mark[a] == mark[b])merge(a,b); //这里就是使用并查集来记录连通块,因为a b一定是相邻的,而且从农场 A到农场 B之间的唯一路径行走,所以我们只需要merge(a,b)就可以记录了
    }
    for (int i = 1; i <= m; i++)
    {
        int a, b; char c;
        cin >> a >> b;
        cin >> c;
        if (find(a) == find(b) && mark[a] != c)answer[cnt++] = 0;//满足这种情况的才不能是朋友开心,其余的都可以
        else answer[cnt++] = 1;
    }
    for (int i = 0; i < cnt; i++)
        printf("%d", answer[i]);
}

//6 1
//HHGHGH
//1 2
//2 3
//2 4
//1 5
//3 6
//2 6 G
原文地址:https://www.cnblogs.com/Jason66661010/p/13152428.html