codeforces1119F Niyaz and Small Degrees

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/yzyyylx/article/details/89255010

题面

题意

给出一棵有n个点的树,每条边有一个边权,对于 [ 0 , n 1 ] [0,n-1] 的每一个数x求,至少删掉权值和为多少的边后,所有点的度数都小于等于x.

做法

首先考虑对于一个x怎么做,记 d p [ i ] [ 2 ] dp[i][2] 表示第i个点与其父亲之间的边是否删去时,以i为根的子树最小要删去权值和为多少的点,转移时可以用堆处理出所有子节点t中 d p [ t ] [ 1 ] + v a l d p [ t ] [ 0 ] dp[t][1]+val-dp[t][0] 最小的几个值, v a l val 表示点 i i 与点 t t 之间的边的权值.
对于所有度数小于等于x的点来说,与它相连的所有边是否被删去,仅与边的另一头有关,因此可以将这条边的权值加入到另一头的堆中,然后在dp时只要考虑所有度数大于x的点即可,这样的总复杂度就是 i = 0 n 1 j = 1 n [ d s [ j ] > i ] = i = 1 n d s [ i ] = n , d s [ i ] \sum_{i=0}^{n-1}\sum_{j=1}^n{[ds[j]>i]}=\sum_{i=1}^nds[i]=n,ds[i] 表示点 i i 的度数.

代码

#include<bits/stdc++.h>
#define ll long long
#define P pair<ll,ll>
#define mp make_pair
#define fi first
#define se second
#define N 250100
using namespace std;

ll n,md,sum,ans,ds[N],vis[N],nxt[N],dp[N][2];
struct Pq
{
	ll size,sum;
	priority_queue<ll>a,b;
	void push(ll u){a.push(u),size++,sum+=u;}
	void del(ll u){b.push(u),size--,sum-=u;}
	void cle(){for(;!a.empty()&&!b.empty()&&a.top()==b.top();a.pop(),b.pop());}
	void pop(){cle(),sum-=a.top(),a.pop(),size--;}
	bool empty(){cle();return a.empty();}
	ll top(){cle();return a.top();}
}pq[N];
vector<P>to[N];
vector<ll>have[N],use,gg;

inline bool cmp(P u,P v){return ds[u.fi]>ds[v.fi];}
inline void del(ll u)
{
	ll i,t,p,q;
	for(i=0;i<to[u].size();i++)
	{
		p=to[u][i].fi,q=to[u][i].se;
		if(ds[p]<=md) break;
		pq[p].push(q);
	}
}

void dfs(ll now,ll last)
{
	ll i,j,p,q,cnt=ds[now]-md,res=0;
	vis[now]=md;
	for(;pq[now].size>ds[now]-md;pq[now].pop());
	for(i=0;i<to[now].size();i++)
	{
		p=to[now][i].fi;
		if(ds[p]<=md) break;
		if(p==last) continue;
		dfs(p,now);
	}
	use.clear(),gg.clear();
	
	for(i=0;i<to[now].size();i++)
	{
		p=to[now][i].fi,q=to[now][i].se;
		if(ds[p]<=md) break;
		if(p==last) continue;
		ll t=dp[p][1]+q-dp[p][0];
		if(t<0)
		{
			cnt--;
			res+=dp[p][0]+t;
			continue;
		}
		res+=dp[p][0];
		pq[now].push(t);
		use.push_back(t);
	}
	for(;!pq[now].empty()&&pq[now].size>cnt;pq[now].pop()) gg.push_back(pq[now].top());
	dp[now][0]=res+pq[now].sum;
	for(;!pq[now].empty()&&pq[now].size>cnt-1;pq[now].pop()) gg.push_back(pq[now].top());
	dp[now][1]=res+pq[now].sum;
	for(i=0;i<gg.size();i++) pq[now].push(gg[i]);
	for(i=0;i<use.size();i++) pq[now].del(use[i]);
}

int main()
{
	ll i,j,t,p,q,o;
	cin>>n;
	for(i=1;i<n;i++)
	{
		scanf("%lld%lld%lld",&p,&q,&o);
		to[p].push_back(mp(q,o));
		to[q].push_back(mp(p,o));
		ds[p]++,ds[q]++,sum+=o;
	}
	for(i=1;i<=n;i++)
	{
		have[ds[i]].push_back(i);
		sort(to[i].begin(),to[i].end(),cmp);
	}
	for(i=n;i>=1;i--)
	{
		if(have[i+1].size()) nxt[i]=i+1;
		else nxt[i]=nxt[i+1];
	}
	cout<<sum<<" ";
	for(md=1;md<n;md++)
	{
		ans=0;
		for(i=0;i<have[md].size();i++) del(have[md][i]);
		for(i=md+1;i;i=nxt[i])
		{
			for(j=0;j<have[i].size();j++)
			{
				t=have[i][j];
				if(vis[t]==md) continue;
				dfs(t,-1);
				ans+=dp[t][0];
			}
		}
		printf("%lld ",ans);
	}
}

猜你喜欢

转载自blog.csdn.net/yzyyylx/article/details/89255010