codeforces1119F Niyaz and Small Degrees

題面

題意

給出一棵有n個點的樹,每條邊有一個邊權,對於[0,n1][0,n-1]的每一個數x求,至少刪掉權值和爲多少的邊後,所有點的度數都小於等於x.

做法

首先考慮對於一個x怎麼做,記dp[i][2]dp[i][2]表示第i個點與其父親之間的邊是否刪去時,以i爲根的子樹最小要刪去權值和爲多少的點,轉移時可以用堆處理出所有子節點t中dp[t][1]+valdp[t][0]dp[t][1]+val-dp[t][0]最小的幾個值,valval表示點ii與點tt之間的邊的權值.
對於所有度數小於等於x的點來說,與它相連的所有邊是否被刪去,僅與邊的另一頭有關,因此可以將這條邊的權值加入到另一頭的堆中,然後在dp時只要考慮所有度數大於x的點即可,這樣的總複雜度就是i=0n1j=1n[ds[j]>i]=i=1nds[i]=n,ds[i]\sum_{i=0}^{n-1}\sum_{j=1}^n{[ds[j]>i]}=\sum_{i=1}^nds[i]=n,ds[i]表示點ii的度數.

代碼

#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);
	}
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章