CF-Round#628-div2-C题

CF-Round#628-div2-C题

C. Ehab and Path-etic MEXs

传送门

这道题是贪心。
我看了好几遍题目都不大懂题目意思。。真的。。
后来。。强行让自己读了好几遍题目。(英语不大好的原因吧。。)
终于明白了
题目让我们标志每一条边。
题目中定义了MEX(u,v) 。
代表u顶点到v顶点的简单路径(就是不包含回路)中,所标的标识没有出现的最小非负整数。
题目要求我们求出最小的最大的MEX(u, v).按输入要求的顺序输出每条边所标识的标志。
这个地方我想了一会。让最大值最小。
说实话,我自己说的都很绕。。理解了好久=-=qaq

我们可以简单验证一下样例。
我们总可以在一条路径中找到包含标识为0,1的一条简单路径。(不接受任何反驳)
所以我们的MEX(u,v)绝对大于1
我们现在已经知道了绝对大于1.并且让他尽可能小。最小的只有2或者2往上走了
这是一颗树嘛。
所以我们考虑一条简单路径。一个结点的度如果大于等于3.那么一条简单路径绝对不可能包括所有的边。
所以在我们一定可以找到一条路径包含0,1的基础上把任意一个度大于3的结点标记0,1,2…
这样我们就可以保证最大值最小了为2
为什么呢。
上面已经说过了。假设一个结点的度为3,那么这些边被我们标记了0,1,2.
我们不可能找到一条简单路径包括这三条边。
要么就是包含0,1(MEX(…) = 2)
要么就是包含0, 2(MEX(…) = 1)
要么就是包含1, 2 (MEX(…) = 0)
最大值就是2。2就是我们的最小值。啊哈哈哈。对吧。
当然如果度大于3的话。那也是一样的道理,把度大于3的边按顺序标记一下。最大的值也是2.
那么其他边随便你怎么标。都可以。

这就是我们的贪心策略。
最后提醒一下。
题目要求输出的顺序按照输入的顺序。所以我们得记录一下。用pair即可。

我在写代码得时候发现样例二跟我得输出不一样。debug了一下。我在维护答案的时候。有点点冲突。所以存值的时候是从1开始的。然后答案输出的时候-1就可以啦

代码部分:

#include <bits/stdc++.h>
using namespace std;
const int N = 1e5 + 10;

int n;
vector<pair<int, int> > v[N];
int ans[N];

int main()
{
	cin >> n;
	for (int i = 1; i < n; i++)
	{
		int u1, u2;
		scanf ("%d%d", &u1, &u2);
		v[u1].push_back(make_pair(u2, i));
		v[u2].push_back(make_pair(u1, i));
	}
	int cnt = 1;
	for (int i = 1; i <= n; i++)
	{
		if (v[i].size() > 2)
		{
			int t = v[i].size();
			for (int j = 0; j < t; j++)
			{
				ans[v[i][j].second] = cnt++;
			}
			break;
		}
	}
	for (int i = 1; i < n; i++)
	{
		if (!ans[i])
		{
			ans[i] = cnt++;
		}
		cout << ans[i] - 1 << endl;
	}
	return 0;
}
发布了112 篇原创文章 · 获赞 3 · 访问量 2647

猜你喜欢

转载自blog.csdn.net/qq_44624316/article/details/104881910