P5543 [USACO19FEB] The Great Revegetation S 题解

P5543 [USACO19FEB] The Great Revegetation S 题解

简化题意

\(n\) 个变量,第 \(i\) 个变量记为 \(a_i\)。每个变量的值可以为 \(0\) 或者为 \(1\)
\(m\) 个约束条件,第 \(i\) 个要求会首先给出一个字符 SDS 代表相同,D 代表不同。
然后再给出两个数 i j,代表被约束的两个变量。

求有多少种可能的组合。输出其二进制表示

这个简化未必通顺,建议还是去看看原题。

解题思路

不难发现暴力不可行。
有一个性质很容易发现:就是如果两个数被要求相同,实际上就是把它们合并记为一个数了(一个为 1 另一个必须是 1)。
若是被要求不相同,情况也一样(一个为 1 另一个必须是 0)。

看到合并,不难想到用并查集吧。

到这里,我们还忽略了无解的情况(答案为 \(0\))。
而无解的情况判断我们直接用 dfs 来暴力做(有点像二分图)。
这里先建图,若是需要相同的约束,就设边权为 \(0\),反之为 \(1\)
然后对于每个点进行染色。如果一个点被染为了 \(0\),然后又被要求染为 \(1\),那就是无解的情况。

判断完无解,我们只需要用并查集做一遍就行了。
具体操作就看代码。
还有一个坑:其实二进制表示就是个烟幕弹。不难发现,每有一个连通块,答案就乘二,相当于添一个零。

代码部分

#include <bits/stdc++.h>
using namespace std;
vector<pair<int, int> > g[100010];
int n, m;
bool flag = 0;
int fa[100010], color[100010], col[100010];
int find(int x)
{
	return fa[x] == x ? x : fa[x] = find(fa[x]);
}
void dfs(int x)
{
	if(flag)
		return;
	for(int i = 0;i < g[x].size();i ++)
	{
		int y = g[x][i].first, val = g[x][i].second;
		if(color[y] == -1)
		{
			if(!val)
			{
				color[y] = color[x];
				dfs(y);
			}
			else
			{
				color[y] = !color[x];
				dfs(y);
			}
		}
		else
		{
			if((!val && color[x] != color[y]) || (val && color[x] == color[y]))
			{
				flag = 1;
				cout << 0;
				return; 
			}
		}
		if(flag)
			return;
	}
}
int main()
{
    cin >> n >> m;
    for(int i = 1;i <= n;i ++)
    	fa[i] = i;
    memset(color, -1, sizeof(color));
    for(int i = 1;i <= m;i ++)
    {
    	char ch;
    	int a, b;
    	cin >> ch >> a >> b;
    	if(ch == 'S')
    		g[a].push_back({b, 0}), g[b].push_back({a, 0});
    	else
    		g[a].push_back({b, 1}), g[b].push_back({a, 1});
    	int fx = find(a), fy = find(b);
    	if(fx == fy)
    		continue;
    	fa[fx] = fy;
	}
	
	for(int i = 1;i <= n;i ++)
	{
		if(color[i] == -1)
		{
			color[i] = 1;
			dfs(i);
		}
	}
	
	if(flag)
		return 0;
	int cnt = 0;
	for(int i = 1;i <= n;i ++)
	{
		find(i);
		if(!col[fa[i]])
		{
			col[fa[i]] = 1;
			cnt ++;
		}
	}
	
	cout << 1;
	while(cnt --)
		cout << 0;
    return 0;
}

posted on 2026-08-25 23:03  Leo_29  阅读(5)  评论(0)    收藏  举报

导航