并查集P5836 [USACO19DEC] Milk Visits S

题目传送门:[https://www.luogu.com.cn/problem/P5836](P5836 [USACO19DEC] Milk Visits S)

我的做法是并查集:对于某个节点的子节点,如果子节点和父节点的类型相同,把子节点合并到父节点的集合之中,否则自己独立一个集合。
在这个思路之上往下dfs。
处理完之后对于每个查询find他们的祖先:
如果他们不在一个集合内的话,那肯定是可以满足两种情况的;如果在一个集合内判断这个集合是否和我要的类型相同。

#include<bits/stdc++.h>
using namespace std;
const int N = 1e5+100;
int n,m;
vector<int>e[N];
int fa[N],w[N],nw[N];
int cnt = 0;
int find(int x)
{
    return fa[x] == x ? x : fa[x] = find(fa[x]);
}
void dfs(int u,int f)
{
    for(int v : e[u])
    {
        if(v == f)continue;
        if(w[v] == w[find(u)])fa[v] = fa[u];
        else nw[fa[v]] = w[v];
        dfs(v,u);
    }
}

int main()
{
    cin>>n>>m;
    for(int i = 1 ; i <= n ; ++i)
    {
        char c;cin>>c;
        w[i] = (c == 'H');
        fa[i] = i;
//         cout<<"w[i]: "<<w[i]<<endl;
    }
    for(int i = 1 ; i < n ; ++i)
    {
        int u,v;cin>>u>>v;
        e[u].push_back(v);
        e[v].push_back(u);
    }
    nw[1] = w[1];
    dfs(1,0);
    while(m--)
    {
        int u,v;
        char c;
        cin>>u>>v>>c;
        int now = (c == 'H');
        int a = find(u),b = find(v);
        if(a != b)cout<<1;
        else{
            if(nw[a] == now)cout<<1;
            else cout<<0;
        }
    }
//     cout<<endl;
//     for(int i = 1 ; i <= n ; ++i)
//         cout<<find(i)<<" \n"[i == n];
    return 0;
}
posted on 2025-08-18 19:43  钟一一  阅读(13)  评论(0)    收藏  举报