Codeforces Round #628 (Div. 2) C. Ehab and Path-etic MEXs

C. Ehab and Path-etic MEXs

题目链接-C. Ehab and Path-etic MEXs
Codeforces Round #628 (Div. 2) C. Ehab and Path-etic MEXs_第1张图片
Codeforces Round #628 (Div. 2) C. Ehab and Path-etic MEXs_第2张图片
Note
The tree from the second sample:
Codeforces Round #628 (Div. 2) C. Ehab and Path-etic MEXs_第3张图片
题目大意
给一颗树,有 n 个顶点,给这个树的边分别编号为 0 (n−2),问怎样编使得对于树上任意两点 u,v 的最大 mex(u,v) 值最小。mex(u,v) 表示由 u 到 v 点的简单路径的长度构成的集合中,没有出现的最小非负整数

解题思路
贪心构造

  • 如果存在某一个节点度数大于等于3(即不为链),那么三个出边分别连0 1 2就可以了,剩下的随便连,这样所有路径都不会同时经过0 1 2这三条边,所以mex最大值就是2
  • 如果没有点度数大于等于3,那么这个树就是一条链,怎么赋值都无所谓了
  • 具体操作见代码

附上代码

#include
#define int long long
#define lowbit(x) (x &(-x))
using namespace std;
const int INF=0x3f3f3f3f;
const double PI=acos(-1.0);
const double eps=1e-10;
const int M=1e9+7;
const int N=1e5+5;
typedef long long ll;
typedef pair<int,int> PII;
bool vis[N];
vector<int> vt[N];
int u[N],v[N],ans[N];
signed main(){
	ios::sync_with_stdio(false);
	cin.tie(0);cout.tie(0);
	
	int n;
	cin>>n;
	for(int i=1;i<n;i++){
		cin>>u[i]>>v[i];
		vt[u[i]].push_back(v[i]);
		vt[v[i]].push_back(u[i]);
	}
	int cnt=0;
	for(int i=1;i<n;i++){
		if(vt[u[i]].size()==1||vt[v[i]].size()==1){
			vis[i]=1;
			ans[i]=cnt++;
		}
	}
	for(int i=1;i<n;i++){
		if(!vis[i])
			ans[i]=cnt++;
	}
	for(int i=1;i<n;i++)
		cout<<ans[i]<<endl;
	return 0;
}

你可能感兴趣的:(codeforces,图论)