标签:pac ios space span opera 简单 代码 一个 其他
题意:
给定一棵 n 个节点 n-1 条边的树
你需要给这棵树的每条边打上编号
编号从 0 开始到 n-2
定义 MEX( u,v ) 表示从节点 u 走到节点 v 的途中所经过的边中没有出现过的编号的最小非负整数
为了使得最大的 MEX( u,v ) 值最小
问应该如何编号
解题思路:
两个节点一条边直接特判
因为这是一棵树,所以我们可以从节点的方向下手
如果这棵树被构造成了一个单链,即除了首尾节点只有一个相邻节点外,其他节点都只有两个相邻节点
这种情况下不论怎么编号,答案都不会变,即最大MEX = n-1
但如果这棵树不是单链,即出现了某个节点含有三个及以上的相邻节点的话
如图
因为树上两个节点之间有且仅有一条简单路径
也就是说,对于连接同一个节点的三条边,或者是更多条边,一条简单路径最多只能包含其中的两条边
因此,根据MEX的定义
我们只要将编号 0 1 2 给定在这个节点相邻的边上即可
如果一条简单路径没有经过编号 0 的边,那么MEX的结果一定为0
如果一条简单路径经过了编号 0 的边但是没有经过编号 1 的边,那么MEX的结果一定为1
如果一条简单路径同时经过了编号 0 和编号 1 ,那么绝对不会经过编号 2 ,那么MEX的结果一定为2
这样就做到了最小化MEX最大值,即最大值为 2
另外,只要一个节点相邻节点数大于等于 3 ,都可以按照上述方式处理,只要简单路径不经过这个节点,MEX必定为 0
代码分析:
毕竟只要选相邻节点数尽量大的都行,方便起见直接对相邻节点数这个关键点进行了降序排序,pid 直接赋值为最大的那个节点的 id
只要将 0 1 2 三个编号给定在这个节点相邻边上即可
为了方便直接定义 l=0 r=n-2
让所有这个节点的相邻边从小到大赋值(主要把 0 1 2 送出去),其余边从大到小赋值(当作随机吧)
(186ms / 1000ms)
1 #include<bits/stdc++.h> 2 using namespace std; 3 4 struct edge 5 { 6 int u,v; 7 }ar[200050]; 8 struct node 9 { 10 int id,degree; 11 bool operator < (const node& a) const 12 { 13 return degree>a.degree;//按照连接的边数从大到小排序 14 } 15 }br[200050]; 16 17 void solve() 18 { 19 int n,i; 20 cin>>n; 21 if(n==2) 22 { 23 cout<<"0\n"; 24 return; 25 } 26 for(i=1;i<=n;i++) 27 { 28 br[i].id=i; 29 br[i].degree=0; 30 } 31 for(i=1;i<n;i++) 32 { 33 cin>>ar[i].u>>ar[i].v; 34 br[ar[i].u].degree++; 35 br[ar[i].v].degree++; 36 } 37 sort(br+1,br+1+n); 38 39 int pid=br[1].id,l=0,r=n-2; 40 for(i=1;i<n;i++) 41 { 42 if(ar[i].u==pid||ar[i].v==pid) 43 cout<<l++<<‘\n‘;//相邻边从小到大排序 44 else 45 cout<<r--<<‘\n‘;//其余从大到小 46 } 47 } 48 49 int main() 50 { 51 ios::sync_with_stdio(0); 52 cin.tie(0);cout.tie(0); 53 solve(); 54 55 return 0; 56 }
Codeforces 1325C - Ehab and Path-etic MEXs
标签:pac ios space span opera 简单 代码 一个 其他
原文地址:https://www.cnblogs.com/stelayuri/p/12495689.html