1325C

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;
}
posted @ 2021-10-09 22:41  指引盗寇入太行  阅读(64)  评论(0编辑  收藏  举报