Codeforces Round #774 (Div. 2) D 题解

79 阅读1分钟

题目链接

思路

n>2n>2时,两个good vertex是不可能相邻的,那么good vertex的最大值就是树的最大独立集。考虑已知最大独立集是哪些之后怎么让权值最小。显然普通点全部是11,good vertex是它的度数可以保证最小权值和。设dp_[u][s]dp\_[u][s]为节点uu是(s=1s=1)/不是(s=0s=0)good vertex时子树在保证good vertex最多的前提下的最小权值和,在求最大独立集的同时把这个一起算出来就可以了。

代码

#include<bits/stdc++.h>
#define rep(i,st,ed) for(int i=st;i<=ed;++i)
#define bl(u,i) for(int i=head[u];i;i=e[i].nxt)
#define en puts("")
#define LLM LONG_LONG_MAX
#define LLm LONG_LONG_MIN
#define pii pair<ll,ll> 
typedef long long ll;
typedef double db;
using namespace std;
const ll INF=0x3f3f3f3f;
void read() {}
void OP() {}
void op() {}
template <typename T, typename... T2>
inline void read(T &_, T2 &... oth)
{
    int __=0;
    _=0;
    char ch=getchar();
    while(!isdigit(ch))
    {
        if(ch=='-')
            __=1;
        ch=getchar();
    }
    while(isdigit(ch))
    {
        _=_*10+ch-48;
        ch=getchar();
    }
    _=__?-_:_;
    read(oth...);
}
template <typename T>
void Out(T _)
{
    if(_<0)
    {
        putchar('-');
        _=-_;
    }
    if(_>=10)
       Out(_/10);
    putchar(_%10+'0');
}
template <typename T, typename... T2>
inline void OP(T _, T2... oth)
{
	Out(_);
	putchar('\n');
	OP(oth...);
}
template <typename T, typename... T2>
inline void op(T _, T2... oth)
{
	Out(_);
	putchar(' ');
	op(oth...);
}
/*#################################*/
const ll N=2E5+10;
ll n,cnt,tot;
ll dp[N][2],w[N],dp_[N][2];
vector<ll> edge[N];
void add_edge(ll u,ll v,ll flag)
{
	edge[u].emplace_back(v);
	if(flag)
		add_edge(v,u,0);
}
void dfs(ll u,ll fa)
{
	dp[u][1]=1;
	dp_[u][1]=edge[u].size();
	dp_[u][0]=1;
	for(auto v:edge[u])
	{
		if(v==fa)
			continue;
		dfs(v,u);
		dp[u][0]+=max(dp[v][0],dp[v][1]);
		dp[u][1]+=dp[v][0];
		
		if(dp[v][0]>dp[v][1])
			dp_[u][0]+=dp_[v][0];
		else if(dp[v][0]<dp[v][1])
			dp_[u][0]+=dp_[v][1];
		else if(dp_[v][0]<dp_[v][1])
			dp_[u][0]+=dp_[v][0];
		else
			dp_[u][0]+=dp_[v][1];
		dp_[u][1]+=dp_[v][0];
	}
}
void gg(ll u,ll fa,ll col)
{
	if(col==1)
	{
		w[u]=edge[u].size();
		++cnt;
	}
	else
		w[u]=1;
	tot+=w[u];
	for(auto v:edge[u])
	{
		if(v==fa)
			continue;
		if(col==1)
			gg(v,u,0);
		else
		{
			if(dp[v][0]>dp[v][1])
				gg(v,u,0);
			else if(dp[v][0]<dp[v][1])
				gg(v,u,1);
			else if(dp_[v][0]<dp_[v][1])
				gg(v,u,0);
			else
				gg(v,u,1);
		}
	}
}
int main()
{
	read(n);
	ll u,v;
	rep(i,1,n-1)
	{
		read(u,v);
		add_edge(u,v,1);
	}
	if(n==2)
	{
		op(2,2);
		en;
		op(1,1);
		return 0;
	}
	ll p=1;
	dfs(p,0);
	if(dp[p][0]>dp[p][1])
		gg(p,0,0);
	else if(dp[p][0]<dp[p][1])
		gg(p,0,1);
	else if(dp_[p][0]<dp_[p][1])
		gg(p,0,0);
	else
		gg(p,0,1);
	op(cnt,tot);
	en;
	rep(i,1,n)
		op(w[i]);
	en;
}