【构造,贪心】cf1141G-Privatization of Roads in Treeland

题意

给你一个无根树,然后给每一条边标上号,要求每个点所连的边的号不能有重复。

现在给你一个“优惠”,你可以忽略一些点的要求

问你最少要多少个号

把这样的树输出出来

题解

考虑每个点需要多少个号,就是这个点的度数,统计每个点的度数,然后忽略度数最高的k个点。

即号数等于第k+1大的度数(注意有可能忽略所有的点,但是你再怎么也得有一个号才行)

然后随便随便选一个点,开始贪心dfs就行了

代码

#include <bits/stdc++.h>
​
using namespace std;
const int maxn=200000+100;
vector<int> g[maxn];
struct point{
    int u,v;
    point(int a=0,int b=0):u(a),v(b){}
};
bool operator <(const point& a,const point& b){
    if(a.u==b.u)return a.v<b.v;
    return a.u<b.u;
}
point p[maxn];
int d[maxn],n,k;
int m;
map<point,int> mm;
void dfs(int i,int fa,int x)
{
    int num=g[i].size();
    int v;
    int cnt=1;
    for(int j=0;j<num;j++){
        v=g[i][j];
        if(v==fa)continue;
        if(cnt==x)cnt++;
        if(num<=m){
            mm[point(min(v,i),max(v,i))]=cnt;
            dfs(v,i,cnt);
        }
        else {
            mm[point(min(v,i),max(v,i))]=1;
            dfs(v,i,1);
        }
        ++cnt;
    }
}
int main()
{
    cin>>n>>k;
    int a,b;
    for(int i=1;i<n;i++){
        cin>>a>>b;
        if(a>b)swap(a,b);
        g[a].push_back(b);
        g[b].push_back(a);
        d[a]--;
        d[b]--;
        p[i].u=a;
        p[i].v=b;
    }
    sort(d,d+n);
    m=-d[k];
    m=max(m,1);
    int num=g[1].size(),v;
    for(int i=0;i<num;i++){
        v=g[1][i];
        if(num<=m){
            mm[point(min(v,1),max(v,1))]=i+1;
            dfs(v,1,i+1);
        }
        else {
            mm[point(min(v,1),max(v,1))]=1;
            dfs(v,1,1);
        }
    }
    cout<<m<<endl;
    for(int i=1;i<n;i++)
        cout<<mm[p[i]]<<' ';
    return 0;
}
​

猜你喜欢

转载自blog.csdn.net/wang_viscaria/article/details/92669479