USACO-Silver-Milk Visits-构图/联通性的维护

一.题面

Farmer John is planning to build NN (1≤N≤1051≤N≤105) farms that will be connected by N−1N−1 roads, forming a tree (i.e., all farms are reachable from each-other, and there are no cycles). Each farm contains a cow, whose breed is either Guernsey or Holstein.

Farmer John's MM friends (1≤M≤1051≤M≤105) often come to visit him. During a visit with friend ii, Farmer John will walk with his friend along the unique path of roads from farm AiAi to farm BiBi (it may be the case that Ai=BiAi=Bi). Additionally, they can try some milk from any cow along the path they walk. Since most of Farmer John's friends are also farmers, they have very strong preferences regarding milk. Some of his friends will only drink Guernsey milk, while the remainder will only drink Holstein milk. Any of Farmer John's friends will only be happy if they can drink their preferred type of milk during their visit.

Please determine whether each friend will be happy after visiting.

SCORING:

  • Test cases 2-5 satisfy N≤103,M≤2⋅103.N≤103,M≤2⋅103.

INPUT FORMAT (file milkvisits.in):

The first line contains the two integers NN and MM.

The second line contains a string of length NN. The iith character of the string is 'G' if the cow in the iith farm is a Guernsey, or 'H' if the cow in the iith farm is a Holstein.

The next N−1N−1 lines each contain two distinct integers XX and YY (1≤X,Y≤N1≤X,Y≤N), indicating that there is a road between farms XX and YY.

The next MM lines contain integers AiAi, BiBi, and a character CiCi. AiAi and BiBi represent the endpoints of the path walked during friend ii's visit, while CiCi is either G or H if the iith friend prefers Guernsey milk or Holstein milk.

OUTPUT FORMAT (file milkvisits.out):

Print a binary string of length MM. The iith character of the string should be '1' if the iith friend will be happy, or '0' otherwise.

SAMPLE INPUT:

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

SAMPLE OUTPUT:

10110 

USACO 

题目会告诉我们哪些点之间是连通的,并要求我们求出在i-j点的路径中,是否具有某一个特定的字母

二.算法详解 

  很明显,这道题要构建一个连通图 ,关于连通图的构建方法,在前面的博客我们已经讲解过了,大家可以自行翻阅。但是这个题的难点在于,在创建好一张完整的图之后,在后面m次的判定中,我们每一次都要沿同一张图搜索一遍,这样的复杂度我们是接受不了的,那么我们该如何优化呢。

  显然,这道题需要优化的部分在于:每一次的判定,我们并不希望将这张图走一遍,也就是希望可以将判定的过程优化为O(1),仅通过两个点的信息就能判断出整个路径中出现的字母。注意我们这里判定的是路径中出现的颜色,然而这道题的特殊性在于只有两种颜色。那么也就是说如果这条路径上颜色是纯的(即整条路径上的每个点的颜色都相同),那么我们可以用任意一个点来判定,只要他的颜色是G,那么整条路径就是G;如果它的颜色是H,那么整条路径都是H。并且只要这条路径上的颜色不纯,那么我们可以直接确定他同时包含两种颜色,那么直接输出1.这样的特殊性质只在有且仅有两种颜色的图上有。

因此问题转化为:通过无向图的存储将纯色路径存储在一起,这样如果我们判定两个点处于同一个连通图块中,我们可以确定这两点之间的路径是纯的。所以我们存储的条件便有两条:1.可达 2.同色。也就是说我们改变了构图的方式。比如这道题的样例中:1,2,4应该在一个连通块中;3应该是一个连通块;5应该是一个连通块。

int a, b;
		cin >> a >> b;
		if (c[a] == c[b]) {
			E[a].push_back(b);
			E[b].push_back(a);
		}

所以这m次的判定就改为:1.判断两点是否处于一个连通块中2.若两点在一个连通块里,那么判定这个连通块的颜色与条件给的是否相同。

	if (visit[a] != visit[b]) {
			ans[i] = '1';
		} else if (c[visit[a]] == s) {
			ans[i] = '1';
		} else
			ans[i] = '0';

接下来的问题就是如何维护图的连通性,也就是如何划分连通块。这里我们可以将所有处于一个连通块的点打上相同的标记,这样所有标记相同的点就是一个连通块中的点。这个标记怎么打呢:对于一个连通块,我们让它其中所有点的标记都统一为我们第一个访问点的id就可以了。这个过程就在搜索中实现。

void dfs(int now) {
	for (auto next : E[now]) {
		if (visit[next] == 0) {
			visit[next] = visit[now];
			dfs(next);
		}
	}
}

三.完整代码

#include <bits/stdc++.h>
using namespace std;
int n, m;
const int maxn = 1e5 + 5;
vector<int>E[maxn];
int visit[maxn];
char c[maxn];
char ans[maxn];

void dfs(int now) {
	for (auto next : E[now]) {
		if (visit[next] == 0) {
			visit[next] = visit[now];
			dfs(next);
		}
	}
}

int main() {
	freopen("milkvisits.in", "r", stdin);
	freopen("milkvisits.out", "w", stdout);
	cin >> n >> m;
	for (int i = 1; i <= n; i++) {
		cin >> c[i];
	}
	int tmp = n - 1;
	while (tmp--) {
		int a, b;
		cin >> a >> b;
		if (c[a] == c[b]) {
			E[a].push_back(b);
			E[b].push_back(a);
		}
	}
	for (int i = 1; i <= n; i++) {
		if (visit[i] == 0) {
			visit[i] = i;
			dfs(i);
		}
	}
	for (int i = 1; i <= m; i++) {
		int a, b;
		char s;
		cin >> a >> b >> s;
		if (visit[a] != visit[b]) {
			ans[i] = '1';
		} else if (c[visit[a]] == s) {
			ans[i] = '1';
		} else
			ans[i] = '0';
	}
	for (int i = 1; i <= m; i++) {
		cout << ans[i];
	}
	return 0;
}

四.总结

1.对于只有两种颜色的图,有一个特殊性质:若某条子路径的颜色是纯的,那么它只包含其中任意一点的颜色;若它的颜色不纯,那么它必定包含所有的颜色种类。

2.构建无向图:构图的条件是灵活的,不一定只要两点之间可达就能构成连通块,我们要对“连通”给出自己的定义

3.连通性的维护:我们可以将属于同一连通块的点打上相同的标记,来维护这些点之间的连通性。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值