树中所有点到某个点的距离和中,到重心的距离和是最小的,如果有两个距离和,他们的距离和一样。
把两棵树通过一条边相连,新的树的重心在原来两棵树重心的连线上。
一棵树添加或者删除一个节点,树的重心最多只移动一条边的位置。
一棵树最多有两个重心,且相邻
theme:给定一棵树,求树的重心节点及删掉重心后形成的森林中最大的树的节点数。
//theme:给定一棵树,求树的重心节点及删掉重心后形成的森林中最大的树的节点数。
/*求树的重心主要是利用了DP的思想,size[x]表示以i点为根节点的子树的节点数,f[x]表示以x为根节点时,节点最多的子树节点数是多少*/
#include
#include
using namespace std;
const int N=20005;
struct edge
{
int to,next;
}e[N*2];
int head[N],t,n,i,x,y,k,size[N],f[N],root,MIN;
inline void read(int &x)
{
x=0; char ch=getchar();
while (ch<'0'||ch>'9') ch=getchar();
while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
}
inline void write(int x)
{
if (x/10) write(x/10);
putchar(x%10+'0');
}
inline void add(int x,int y)
{
e[++k].to=y; e[k].next=head[x]; head[x]=k;
}
inline int max(int a,int b)
{
return a>b?a:b;
}
inline void getroot(int now,int fa)
{
size[now]=1; f[now]=0;
for (int i=head[now];i!=-1;i=e[i].next)
if (e[i].to!=fa)
{
getroot(e[i].to,now);
size[now]+=size[e[i].to];
f[now]=max(f[now],size[e[i].to]);
}
f[now]=max(f[now],n-size[now]);
if (f[now]
求法很简单,先任选一点做一次BFS,找出与它距离最远的点,那么该点就是树的直径的一个端点。 再以此端点为起点再做一次BFS,找出与它距离最远的点,那么另一个点就是树的直径的另一个端点,它们之间的距离就是树的直径。
//求树的直径,即距离最远的两点间的距离
#include
#include
using namespace std;
const int N=10005;
struct egde
{
int to,next,v;
}e[N];
int head[N],q[N],dis[N],x,y,z,k,ans;
bool vis[N];
inline void add(int x,int y,int z)
{
e[++k].to=y; e[k].v=z; e[k].next=head[x]; head[x]=k;
}
inline int BFS(int now)
{
memset(vis,0,sizeof(vis));
int H=0,T=1,num;
vis[now]=1; dis[now]=0; q[1]=now; ans=-1;
while (Hans) ans=dis[x],num=x;
for (int i=head[x];i!=-1;i=e[i].next)
if (!vis[e[i].to])
{
vis[e[i].to]=1;
dis[e[i].to]=dis[x]+e[i].v;
q[++T]=e[i].to;
}
}
return num;
}
int main()
{
memset(head,-1,sizeof(head));
memset(e,-1,sizeof(e));
while (scanf("%d%d%d",&x,&y,&z)!=EOF)
add(x,y,z),add(y,x,z);
BFS(BFS(1));
printf("%d",ans);
return 0;
}
theme:给定一棵树,求树上不完全相同两条路径的交的长度。路径长度定义为边的长度。3<=n<=2e5
solution:其实就是求树的直径-1。而树的直径就是两遍dfs.
#include
#include
#include
using namespace std;
#define far(i,t,n) for(int i=t;iv[maxn];
int ans;
void dfs(int now,int pre,int &node,int l)
{
if(v[now].size()==1&&v[now][0]==pre)
{
if(ans>n;
int m=n-1;
far(i,0,m)
{
int f,t;
scanf("%d%d",&f,&t);
v[f].pb(t);
v[t].pb(f);
}
int node=-1;
dfs(1,0,node,0);
ans=0;
int e=-1;
dfs(node,0,e,0);
cout<