求助站外题
  • 板块学术版
  • 楼主AAA404
  • 当前回复21
  • 已保存回复21
  • 发布时间2023/8/11 20:14
  • 上次更新2023/11/3 04:24:21
查看原帖
求助站外题
723198
AAA404楼主2023/8/11 20:14

模拟赛原题,应该是ybtoj上的

给定一棵 NN 个节点的树,要求增加若干条边,把这棵树扩充为完全图,并满足图的唯一最小生成树仍然是这棵树。

求增加的边的权值总和最小是多少。

注意: 树中的所有边权均为整数,且新加的所有边权也必须为整数。

思路是:

画图可以发现:对于任意两点之间要新建的边,其权值必定大于两点原有路径上的权值最大值

然后就是一个边转点树剖

但是莫名RE

#include<bits/stdc++.h>
using namespace std;
const int N=6005;
int n,TT,dep[N],son[N],top[N],id[N],rk[N],rr[N],fa[N],a[N],b[N],w[N],cnt,sz[N];
long long ans;
vector<int>v[N];
bool vis[N][N];
struct node{
	int l,r,val,tag;
};
struct Tree{
	node Tr[N<<2];
	#define ls(id) id<<1
	#define rs(id) id<<1|1
	inline void pushup(int id)
	{
		Tr[id].val=max(Tr[ls(id)].val,Tr[rs(id)].val);
		return;
	}
	inline void pushdown(int id)
	{
		if(Tr[id].tag!=-1)
		{
			Tr[ls(id)].val=Tr[rs(id)].val=Tr[id].tag;
			Tr[ls(id)].tag=Tr[rs(id)].tag=Tr[id].tag;
			Tr[id].tag=-1;
		}
		return;
	}
	inline void build(int id,int l,int r)
	{
		Tr[id]={l,r,0,-1};
		if(l==r)
		{
			Tr[id].val=w[rk[rr[l]]];
			return;
		}
		int mid=l+r>>1;
		build(ls(id),l,mid);
		build(rs(id),mid+1,r);
		pushup(id);
		return;
	}
	inline void modify(int id,int l,int r,int k)
	{
		if(l<=Tr[id].l&&Tr[id].r<=r)
		{
			Tr[id].tag=k;
			Tr[id].val=k;
			return;
		}
		pushdown(id);
		int mid=Tr[id].l+Tr[id].r>>1;
		if(l<=mid)modify(ls(id),l,r,k);
		if(r>mid)modify(rs(id),l,r,k);
		pushup(id);
		return;
	}
	inline int query(int id,int l,int r)
	{
		if(l<=Tr[id].l&&Tr[id].r<=r)
		{
			return Tr[id].val;
		}
		pushdown(id);
		int mid=Tr[id].l+Tr[id].r>>1,ans=0;
		if(l<=mid)ans=max(ans,query(ls(id),l,r));
		if(r>mid)ans=max(ans,query(rs(id),l,r));
		return ans;
	} 
}T;
inline void init()
{
	for(int i=1;i<=n;i++)
	{
		memset(vis[i],0,sizeof vis[i]);
		vector<int>().swap(v[i]);
	}
	if(n!=0)
	T.modify(1,1,n,0);
	T.Tr[1]={0,0,0,-1};
	ans=0;
	cnt=0;
	return;
}
inline void dfs1(int p,int faa)
{
	sz[p]=1;
	dep[p]=dep[faa]+1;
	fa[p]=faa;
	for(int t:v[p])
	{
		if(t==faa)continue;
		dfs1(t,p);
		sz[p]+=sz[t];
		if(sz[t]>sz[son[p]])son[p]=t;
	}
	return;
}
inline void dfs2(int p,int faa)
{
	top[p]=faa;
	id[p]=++cnt;
	rk[cnt]=p;
	if(!son[p])return;
	dfs2(son[p],faa);
	for(int t:v[p])
	{
		if(t==fa[p]||t==son[p])continue;
		dfs2(t,t);
	}
	return;
}
inline int query(int a,int b)
{
	int res=0;
	while(top[a]!=top[b])
	{
		if(dep[top[a]]<dep[top[b]])swap(a,b);
		res=max(res,T.query(1,id[top[a]],id[a]));
		a=fa[top[a]];
	}
	if(dep[a]>dep[b])swap(a,b);
	res=max(res,T.query(1,id[a]+1,id[b]));
	return res;
}
int main()
{
	cin>>TT;
	while(TT--)
	{
		init();
		cin>>n;
		for(int i=1;i<=n-1;i++)
		{
			cin>>a[i]>>b[i]>>w[i+1];
			v[a[i]].push_back(b[i]);
			v[b[i]].push_back(a[i]);
			vis[a[i]][b[i]]=vis[b[i]][a[i]]=1;
		}
		dfs1(1,0);
		dfs2(1,1);
		for(int i=1;i<=n-1;i++)
		{
			if(dep[a[i]]<dep[b[i]])rr[i+1]=b[i];
			else rr[i+1]=a[i];
		}
		T.build(1,1,n);
		for(int i=1;i<=n;i++)
		{
			for(int j=1;j<=n;j++)
			{
				if(vis[i][j]||i==j)continue;
				ans+=1ll*(query(i,j)+1);
				vis[i][j]=vis[j][i]=1;
			}
		}
		printf("%lld\n",ans);
	}
	return 0;
}

2023/8/11 20:14
加载中...