标签:max continue mat amp cpp 递归 mes char ret
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<queue>
#include<map>
#include<set>
#define ll long long
using namespace std;
inline int read(){
int x=0,o=1;char ch=getchar();
while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar();
if(ch=='-')o=-1,ch=getchar();
while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
return x*o;
}
const int N=1e5+5;
int dis[N],pre[N],a[N],c[N],dist[N],bj[N];
int tot,head[N],nxt[N<<1],to[N<<1];
struct ppx{int val,id;}b[N];
inline bool cmp(ppx x,ppx y){return x.val>y.val;}
inline void add(int a,int b){nxt[++tot]=head[a];head[a]=tot;to[tot]=b;}
inline void dfs1(int u,int fa){
for(int i=head[u];i;i=nxt[i]){
int v=to[i];if(v==fa)continue;
dis[v]=dis[u]+1;dfs1(v,u);
}
}
inline void dfs2(int u,int fa){
for(int i=head[u];i;i=nxt[i]){
int v=to[i];if(v==fa)continue;
dis[v]=dis[u]+1;pre[v]=u;dfs2(v,u);
}
}
inline void dfs3(int u,int fa){
dist[u]=dis[u];
for(int i=head[u];i;i=nxt[i]){
int v=to[i];if(v==fa)continue;
dis[v]=dis[u]+1;dfs3(v,u);
dist[u]=max(dist[u],dist[v]);
}
}
int main(){
int n=read(),k=read();
for(int i=1;i<n;++i){int a=read(),b=read();add(a,b);add(b,a);}//存图
dfs1(1,0);int maxn=0,pos1,pos2;//第一次以任意一个节点为根dfs
for(int i=1;i<=n;++i)if(dis[i]>maxn){maxn=dis[i];pos1=i;}//找到距离最远的那个点pos1
memset(dis,0,sizeof(dis));dfs2(pos1,0);maxn=0;//以pos1为根第二次dfs
for(int i=1;i<=n;++i)if(dis[i]>maxn){maxn=dis[i];pos2=i;}//找到距离最远的那个节点pos2,此时pos1-pos2就是树的直径
int tot=0;while(pos2!=pos1){a[++tot]=pos2;pos2=pre[pos2];}//递归存储直径上的所有节点
a[++tot]=pos1;reverse(a+1,a+tot+1);
int root=a[(tot+1)/2];memset(dis,0,sizeof(dis));dfs3(root,0);//找到中点,以其为根dfs
for(int i=1;i<=n;++i){
b[i].val=dist[i]-dis[i];
b[i].id=i;c[i]=b[i].val;
}
sort(b+1,b+n+1,cmp);
for(int i=1;i<=k;++i)bj[b[i].id]=1;//选出k个核心节点
int ans=0;
for(int i=1;i<=n;++i)
if(!bj[i])ans=max(c[i]+1,ans);//不是核心节点,就计算贡献
printf("%d\n",ans);
return 0;
}
标签:max continue mat amp cpp 递归 mes char ret
原文地址:https://www.cnblogs.com/PPXppx/p/11563524.html