题目描述:
由于 zzq 太懒了,所以这题没有题目背景。
有一棵树,树上有 n 个点,每条边上有一个非负边权。
在这 n 个点中有 k 个特殊点,其中 k 为偶数。定义两个点的距离为它们在树上的简单路径上的边权之和。你需要将这 k 个点配成k/2个互不相交的对,并最大化每一对点的距离之和。
思路:
一个结论,这k条路经至少会交于一个公共点,可以证明如果没有交于一点一定存在一个更优的方案并且交于一点。
于是考虑去求所有选中的点到相交点的距离,动态维护距离,同时要保证拥有最多选中点的子树大小<=k/2,否则会有路径无法交于相交点。
以下代码:
#include<bits/stdc++.h> #define il inline #define LL long long #define _(d) while(d(isdigit(ch=getchar()))) using namespace std; const int N=1e5+5; bool f[N]; LL ans,dist[N],S; int dfn[N],id,sz[N],mx[N],sum[N],out[N],rt,a[N]; int n,k,head[N],ne[N<<1],to[N<<1],w[N<<1],cnt; il int read(){ int x,f=1;char ch; _(!)ch=='-'?f=-1:f;x=ch^48; _()x=(x<<1)+(x<<3)+(ch^48); return f*x; } il void insert(int x,int y,int z){ ne[++cnt]=head[x];head[x]=cnt; to[cnt]=y;w[cnt]=z; } il void dfs1(int x,int fa){ dfn[x]=++id;sz[x]=f[x]; sum[id]=sum[id-1]+f[x]; if(f[x])S+=dist[x]; for(int i=head[x];i;i=ne[i]){ if(to[i]==fa)continue; dist[to[i]]=dist[x]+w[i]; dfs1(to[i],x); sz[x]+=sz[to[i]]; mx[x]=max(mx[x],sz[to[i]]); } mx[x]=max(mx[x],k-sz[x]); out[x]=id; } il void dfs2(int x,int fa){ if(mx[x]*2<=k&&ans<S)ans=S,rt=x; for(int i=head[x];i;i=ne[i]){ if(fa==to[i])continue; int tot=sum[out[to[i]]]-sum[dfn[to[i]]-1]; S+=1ll*(k-(tot<<1))*w[i]; dfs2(to[i],x); S-=1ll*(k-(tot<<1))*w[i]; } } int tt=0; vector<int> v[N]; struct node{ int x,d,id; bool operator<(const node&t1)const{ return d<t1.d; } }; priority_queue<node> q; il void dfs3(int x,int fa){ if(f[x])v[tt].push_back(x); for(int i=head[x];i;i=ne[i]){ if(fa==to[i])continue; dfs3(to[i],x); } } int main() { n=read();k=read(); for(int i=1;i<n;i++){ int x=read(),y=read(),z=read(); insert(x,y,z);insert(y,x,z); } for(int i=1;i<=k;i++)a[i]=read(),f[a[i]]=1; dfs1(1,0);dfs2(1,0); if(f[rt])v[++tt].push_back(rt); for(int i=head[rt];i;i=ne[i])++tt,dfs3(to[i],rt); for(int i=1;i<=tt;i++){ int x=v[i].size();if(!x)continue; q.push((node){v[i][x-1],x-1,i}); } for(int i=1;i<=(k>>1);i++){ node a=q.top();q.pop(); node b=q.top();q.pop(); printf("%d %d ",a.x,b.x); if(a.d>=1)q.push((node){v[a.id][a.d-1],a.d-1,a.id}); if(b.d>=1)q.push((node){v[b.id][b.d-1],b.d-1,b.id}); } return 0; }