1325C
题意:
n个节点,n-1条边,每条边上有一个数字,0~n-2,求一个编号顺序,使得所有u到v的编号种的mex最小
思路:
两个点u,v之间的mex的贡献肯定有u和v相连的两条边,可以优先把叶子节点全部选成最小,然后任意两个叶子节点之间的mex都只会<=2,中间的路径(不选择根节点)的mex肯定是0,其他的节点随便放即可,
题解:
#include <bits/stdc++.h>
#define eb emplace_back
#define divUp(a,b) (a+b-1)/b
#define mkp(x,y) make_pair(x,y)
#define all(v) begin(v),end(v)
#define int long long
using namespace std;
typedef unsigned long long ull;
typedef pair<int, int> pii;
bool checkP2(int n) {return n > 0 and (n & (n - 1)) == 0;};
const int N = 100010;
vector<int> h[N];
int n;
int cur_min = 0, cur =0;
struct T {
int u, v;
void read() {
cin >> u >> v;
h[u].eb(v);
h[v].eb(u);
}
bool operator<(const T&t)const {
if (t.u != u) return u < t.u;
return v < t.v;
}
} query[N];
map<T, int> mp;
int dfs(int u, int fa) {
int d = 1;
for (auto i : h[u]) {
if (i == fa) continue;
int d1 = dfs(i, u);
if (d1 == 1 ) {
mp[ {u, i}] = cur_min;
mp[ {i, u}] = cur_min;
cur_min++;
} else {
mp[ {u, i}] = cur;
mp[ {i, u}] = cur;
cur--;
}
d += d1;
}
return d;
}
void solve() {
cin >> n;
cur=n-2;
for (int i = 1; i < n; i++) {
query[i].read();
}
dfs(1, -1);
for (int i = 1; i < n; i++) {
auto [x,y]=query[i];
auto res=mp[{x,y}];
// if(res>=n-1) res=cur_min++;
cout<<res<<endl;
}
}
signed main() {
ios::sync_with_stdio(false); cin.tie(0);
//int _; cin >> _; while (_--)
solve();
return 0;
}