题解:CF638C Road Improvement

CF638C Road Improvement 题解

大致思路:

首先第一个问,我们可以通过贪心策略解决,显然 kkk 是所有点中度数最大的点,因为对于每个点,每天最多修一条边,所以答案必然大于等于最大度数。

后面的问,我们可以定一个节点为根,从根开始遍历,用 vector 存每天建的边,还要记录任意一个节点 uuu 与它父亲节点建边的天数,遇到时需要跳过,随后输出即可。

代码实现:

#include<bits/stdc++.h>
const int N = 3e5 + 10;
const int MOD = 1e9 + 7;
using namespace std;
struct Stream {
    enum {
        SIZE = 1000001
    };
    char ibuf[SIZE], *s, *t, obuf[SIZE], *oh;
    bool eof;
 
    Stream() : s(), t(), oh(obuf), eof(false) {}
 
    ~Stream() { fwrite(obuf, 1, oh - obuf, stdout); }
 
    explicit operator bool() const {
        return static_cast<bool>(eof == false);
    }
 
    inline char read() {
        if (s == t) t = (s = ibuf) + fread(ibuf, 1, SIZE, stdin);
        return s == t ? -1 : *s++;
    }
 
    inline Stream &operator>>(char *x) {
        static char c;
        for (c = read(); isspace(c); c = read())
            if (c == -1) {
                eof = true;
                return *this;
            }
        for (; !isspace(c); c = read()) *x = c, ++x;
        *x = 0;
        return *this;
    }
 
    template<typename T>
    inline Stream &operator>>(T &x) {
        static char c;
        static bool iosig;
        for (c = read(), iosig = false; !isdigit(c); c = read()) {
            if (c == -1) {
                eof = true;
                return *this;
            }
            iosig |= c == '-';
        }
        for (x = 0; isdigit(c); c = read()) x = x * 10 + (c ^ '0');
        if (iosig) x = -x;
        return *this;
    }
 
    inline void print(char c) {
        if (oh == obuf + SIZE) {
            fwrite(obuf, 1, SIZE, stdout);
            oh = obuf;
        }
        *oh++ = c;
    }
 
    template<typename T>
    inline void print(T x) {
        static int buf[40], cnt;
        if (x != 0) {
            if (x < 0) print('-'), x = -x;
            for (cnt = 0; x; x /= 10) buf[++cnt] = x % 10 | 48;
            while (cnt) print((char) buf[cnt--]);
        } else print('0');
    }
 
    template<typename T>
    inline Stream &operator<<(const T &x) {
        print(x);
        return *this;
    }
 
    inline void print(const char *x) {
        for (; *x; x++)
            print(*x);
    }
} io;
 
#ifndef DEBUG
#define cin io
#define cout io
#define endl '\n'
#endif
vector < pair < int, int > > f[N];
vector < int > g[N];
int n, dep[N], mx;//dep存度数,通过贪心思想发现k其实就是最大度数,用mx存
void dfs(int d, int x, int fa)
{
    int tmp = 1;
    for(int i = 0;i < f[x].size(); ++ i)
    {
        
        int xx = f[x][i].first;
        int yy = f[x][i].second;
        if(xx == fa) continue;
        if(tmp == d) ++ tmp;//若现在天数到了 u 与父亲相连的天数,则没法再与儿子连
        g[tmp].push_back(yy);
        dfs(tmp ++, xx, x);
    }
}
int main()
{
    cin >> n;
    for(int i = 1;i < n; ++ i)
    {
        int x, y;
        cin >> x >> y;
        f[x].push_back(make_pair(y, i));
        f[y].push_back(make_pair(x, i));
        ++ dep[x]; ++ dep[y];
    }
    for(int i = 1;i <= n; ++ i) mx = max(mx, dep[i]);cout << mx << "\n";
    dfs(0, 1, 0);
    for(int i = 1;i <= mx; ++ i)
    {
        cout << g[i].size() << " ";
        for(int j = 0;j < g[i].size(); ++ j)
        {
            cout << g[i][j] << " ";
        }
        cout << "\n";
    }
    return 0;
}

这样这道题就完成啦!!!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值