Submission #1352735

#TimeUsernameProblemLanguageResultExecution timeMemory
1352735FIFI_cppNetwork (BOI15_net)C++20
100 / 100
308 ms90732 KiB
#include <bits/stdc++.h>
#include <iostream>
#include <vector>
#include <algorithm>
#include <numeric>
#include <cstdlib>
#include <cmath>
#include <queue>
#include <stack>
#include <deque>
#include <fstream>
#include <iterator>
#include <set>
#include <map>
#include <unordered_map>
#include <iomanip>
#include <cctype>
#include <string>
#include <cassert>
#include <set>
#include <bitset>
#include <unordered_set>
#include <numeric>

#define all(a) a.begin(), a.end()
#define fast ios_base::sync_with_stdio(false);cin.tie(NULL);cout.tie(NULL);
#define pb push_back
#define ppi pair<int,pair<int,int>>
#define int int64_t

using namespace std;
//    /\_/\
//   (= ._.)
//   / >  \>
// encouraging cat
const int INF = 10000000000000000;
//const int mod = 1000000007;
const int mod = 998244353;
const int MAXN = 5e5;
//ifstream fin('xor.in');
//ofstream fout('xor.out');
int n;
int rt = 0;
vector<vector<int>> adj;
int tin[MAXN], tout[MAXN];
int sz[MAXN];
int ptr[MAXN], fin[MAXN];
int timer = 0;
vector<int> leafs;
vector<pair<int,int>> res;
int dfs_sz(int node, int p)
{
    int s = 0;
    for (auto edge: adj[node])
    {
        if (edge == p)
        {
            continue;
        }
        s += dfs_sz(edge, node);
    }
    if (adj[node].size() == 1)
    {
        s++;
    }
    for (int i = 0;i < adj[node].size();i++)
    {
        if (p == adj[node][i])
        {
            adj[node].erase(adj[node].begin() + i);
            break;
        }
    }
    sz[node] = s;
    return s;
}
void dfs(int node, int p)
{
    tin[node] = timer++;
    for (auto edge: adj[node])
    {
        dfs(edge, node);
    }
    tout[node] = timer;
    if (adj[node].size() == 0)
    {
        leafs.pb(node);
    }
}
void calc(int node, int p, int rem)
{
    int pos_mx = adj[node][0];
    int tot = 0;
    for (auto edge: adj[node])
    {
        if (edge == p)
        {
            continue;
        }
        if (sz[edge] > sz[pos_mx])
        {
            pos_mx = edge;
        }
        tot += sz[edge];
    }
    if (sz[pos_mx] > tot - sz[pos_mx] + rem)
    {
        calc(pos_mx, node, tot - sz[pos_mx] + rem);
    }
    else
    {
        vector<int> ot;
        for (auto i: leafs)
        {
            if (tin[i] >= tin[node] && tout[i] <= tout[node])
            {
                ;
            }
            else
            {
                ot.pb(i);
            }
        }
        int m = adj[node].size();
        vector<vector<int>> sub(adj[node].size());
        int ptr = 0;
        for (auto i: leafs)
        {
            int real = adj[node][ptr];
            while (ptr < m && !(tin[i] >= tin[real] && tout[i] <= tout[real]) && tin[i] >= tin[real])
            {
                ptr++;
                real = adj[node][ptr];
            }
            if (ptr == m)
            {
                break;
            }
            if (tin[i] >= tin[real] && tout[i] <= tout[real])
            {
                sub[ptr].pb(i);
            }
        }
        sub.pb(ot);
        m++;
        priority_queue<pair<int,int>> pq; // sq, ind
        for (int i = 0;i < m;i++)
        {
            if (sub[i].size() != 0)
            {
                pq.push({sub[i].size(), i});
            }
        }
        while (pq.size() >= 2)
        {
            int va = pq.top().second;
            pq.pop();
            int vb = pq.top().second;
            pq.pop();

            res.pb({sub[va].back(), sub[vb].back()});
            sub[va].pop_back();
            sub[vb].pop_back();

            if (!sub[va].empty())
            {
                pq.push({sub[va].size(), va});
            }

            if (!sub[vb].empty())
            {
                pq.push({sub[vb].size(), vb});
            }
        }
        if (pq.size() == 1)
        {
            int v = sub[pq.top().second][0];
            if (v != leafs[0])
            {
                res.pb({v, leafs[0]});
            }
            else
            {
                res.pb({v, leafs[1]});
            }
        }
    }
}
signed main()
{
    cin >> n;
    adj.resize(n);
    for (int i = 0;i < n - 1;i++)
    {
        int u,v;
        cin >> u >> v;
        u--,v--;
        adj[u].pb(v);
        adj[v].pb(u);
    }
    if (adj[rt].size() == 1)
    {
        rt = adj[rt][0];
    }
    dfs_sz(rt, -1);
    dfs(rt, -1);
    calc(rt, -1, 0);
    cout << res.size() << '\n';
    for (auto m: res)
    {
        cout << m.first + 1 << " " << m.second + 1 << '\n';
    }
    return 0;
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...