(纪中)2436. Milk Visits【并查集】

(File IO): input:milkvisits.in output:milkvisits.out
时间限制: 1000 ms 空间限制: 262144 KB 具体限制
Goto ProblemSet


题目描述
F a r m e r J o h n Farmer John FarmerJohn 计划建造 N ( 1 ≤ N ≤ 1 0 5 ) N(1≤N≤10^5) N1N105个农场,用 N − 1 N−1 N1 条道路连接,构成一棵树(也就是说,所有农场之间都互相可以到达,并且没有环)。每个农场有一头奶牛,品种为更赛牛或荷斯坦牛之一。
F a r m e r J o h n Farmer John FarmerJohn M M M 个朋友 ( 1 ≤ M ≤ 1 0 5 ) (1≤M≤10^5) 1M105经常前来拜访他。在朋友 i i i 拜访之时, F a r m e r J o h n Farmer John FarmerJohn 会与他的朋友沿着从农场 A i Ai Ai 到农场 B i Bi Bi 之间的唯一路径行走(可能有 A i = B i Ai=Bi Ai=Bi)。除此之外,他们还可以品尝他们经过的路径上任意一头奶牛的牛奶。由于 F a r m e r J o h n Farmer John FarmerJohn 的朋友们大多数也是农场主,他们对牛奶有着极强的偏好。他的有些朋友只喝更赛牛的牛奶,其余的只喝荷斯坦牛的牛奶。任何 F a r m e r J o h n Farmer John FarmerJohn 的朋友只有在他们访问时能喝到他们偏好的牛奶才会高兴。
请求出每个朋友在拜访过后是否会高兴。


输入
输入的第一行包含两个整数 N N N M M M
第二行包含一个长为 N N N 的字符串。如果第 i i i 个农场中的奶牛是更赛牛,则字符串中第 i i i个字符为 ′ G ′ 'G' G,如果第 i i i个农场中的奶牛是荷斯坦牛则为 ′ H ′ 'H' H
接下来下 N − 1 N−1 N1 行,每行包含两个不同的整数 X X X Y ( 1 ≤ X , Y ≤ N ) Y(1≤X,Y≤N) Y1X,YN,表示农场 X X X Y Y Y 之间有一条道路。
接下来下 M M M 行,每行包含整数 A i Ai Ai B i Bi Bi,以及一个字符 C i Ci Ci A i Ai Ai B i Bi Bi 表示朋友 i i i拜访时行走的路径的端点, C i Ci Ci ′ G ′ 'G' G ′ H ′ 'H' H 之一,表示第 i i i 个朋友喜欢更赛牛的牛奶或是荷斯坦牛的牛奶。

输出
输出一个长为 M M M 的二进制字符串。如果第 i i i 个朋友会感到高兴,则字符串的第 i i i个字符为 ′ 1 ′ '1' 1,否则为 ′ 0 ′ '0' 0


样例输入
5 5
HHGHG
1 2
2 3
2 4
1 5
1 4 H
1 4 G
1 3 G
1 3 H
5 5 H

样例输出
10110


数据范围限制
测试点 2 − 5 2-5 25 满足 N ≤ 1 0 3 , M ≤ 2 ⋅ 1 0 3 N≤10^3,M≤2⋅10^3 N103,M2103
全部测试点满足 N ≤ 1 0 5 , M ≤ 1 0 5 N≤10^5,M≤10^5 N105,M105


提示
在这里,从农场 1 1 1 到农场 4 4 4的路径包括农场 1 、 2 1、2 12 4 4 4。所有这些农场里都是荷斯坦牛,所以第一个朋友会感到满意,而第二个朋友不会。


解题思路
这道题可以用并查集,把两种牛奶看成两种颜色。
我们可以把同一种颜色合并,然后询问是判断一下一条路的情况就行了:
1. 1. 1. 路上只有一种,那就看看它的颜色与目标一致;
2. 2. 2. 如果路上有两种,就直接1了。


代码

#include<iostream>
#include<cstring>
#include<string>
#include<cstdio>
#include<algorithm>
#include<iomanip>
#include<cmath>
using namespace std;
string s;
char z;
int n,m,x,y,a[100010],ans[100010];
int find(int x)
{
	if(x==a[x])
		return x;
	else
		return a[x]=find(a[x]);
}
int main(){
    freopen("milkvisits.in","r",stdin);
    freopen("milkvisits.out","w",stdout);
    scanf("%d%d",&n,&m);
    cin>>s;
    for(int i=1;i<=n;i++) a[i]=i;
    for(int i=1;i<n;i++)
    {
    	scanf("%d%d",&x,&y);
    	if(s[x-1]==s[y-1])
    		a[find(x)]=find(y);
	}
	for(int i=1;i<=m;i++)
	{
		cin>>x>>y>>z;
		if(find(x)==find(y)&&s[find(x)-1]==z)
			ans[i]=1;
		if(find(x)==find(y)&&s[find(x)-1]!=z)
			ans[i]=0;
		if(find(x)!=find(y))
			ans[i]=1;
	}
	for(int i=1;i<=m;i++)
		printf("%d",ans[i]);
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值