树的直径,又称树的构 长链。 我们将丆 棵树 T
=
{
V
,
E
}
的直径定义为
max(u,v), 也就是说,树中所有最短路径距离的构 大值即为树的直径。 这个树由于没有根结点,其实直径这个概念,还是理解为一 个连通无向无环图的直径 也就是说任何两点之间只有一条路,n个点,n-1条边
这里介绍两种解法
1.俩次BFS或则DFS
首先对任意一个结点做
BFS/DFS
求出最 远的结点,然后以 这个结点为根结点再做 BFS/DFS
到达另一个最远结点。第 一 次 BFS/DFS
到达的结点可以证明一 定是这个图的直径的 一 端,第二次 BFS/DFS
就会达到另外一 端,复杂度为
O
(
n
)
。
2.树形dp
这个暂时还不是很懂,所以还是以后做dp题的时候再说吧
相关的习题(后五个题)
https://vjudge.net/contest/386791#overview
H - Labyrinth
#include<iostream>
#include<cstdio>
using namespace std;
const int N=1100;
int vis[N][N];
char G[N][N];
int to[4][2]={1,0,0,1,-1,0,0,-1};
int n,m;
int maxx,maxy,maxlen;
bool check(int x,int y){
if(x>=0&&x<n&&y>=0&&y<m&&!vis[x][y]&&G[x][y]=='.') return true;
return false;
}
void DFS(int x,int y,int depth){
if(depth>maxlen){
maxlen=depth;
maxx=x,maxy=y;
}
for(int i=0;i<4;i++){
int dx=x+to[i][0];
int dy=y+to[i][1];
if(check(dx,dy)){
vis[dx][dy]=1;
DFS(dx,dy,depth+1);
vis[dx][dy]=0;
}
}
}
int main()
{
int T;
scanf("%d",&T);
while(T--){
bool flag=0;
maxlen=-1;
scanf("%d%d",&m,&n);
for(int i=0;i<n;i++)
for(int j=0;j<m;j++) vis[i][j]=0;
for(int i=0;i<n;i++) scanf("%s",G[i]);
for(int i=0;i<n;i++){
for(int j=0;j<m;j++){
if(G[i][j]=='.') {
flag =1;
vis[i][j]=1;
DFS(i,j,0);
vis[i][j]=0;
break;
}
}
if(flag) break;
}
maxlen=-1;
// for(int i=0;i<n;i++)
// for(int j=0;j<m;j++)
// vis[i][j]=0;
vis[maxx][maxy]=1;
DFS(maxx,maxy,0);
printf("Maximum rope length is %d.\n",maxlen);
}
return 0;
}
I - Cow Marathon
#include<iostream>
#include<cstdio>
using namespace std;
const int N=4e4+10;
int head[N],ne[N*2],w[N*2],e[N*2];
int cnt;
int n,m;
int maxlen;
int maxn;
bool vis[N];
void add(int u,int v,int val){
e[cnt]=v, w[cnt]=val,ne[cnt]=head[u],head[u]=cnt++;
}
void dfs(int x,int depth){
if(depth>maxlen){
maxlen=depth;
maxn=x;
}
for(int i=head[x];i!=-1;i=ne[i]){
int v=e[i];
if(!vis[v]){
vis[v]=1;
dfs(v,depth+w[i]);
vis[v]=0;
}
}
}
int main()
{
cin>>n>>m;
for(int i=1;i<=n;i++) head[i]=-1;
maxlen=-1;
int a,b,c;
char ch;
while(m--){
cin>>a>>b>>c>>ch;
add(a,b,c);
add(b,a,c);
}
vis[1]=1;
dfs(1,0);
vis[1]=0;
dfs(maxn,0);
cout<<maxlen<<endl;
return 0;
}
J - Computer
#include<iostream>
#include<cstdio>
using namespace std;
const int N = 1e4+10;
int head[N],ne[N*2],w[N*2],e[N*2];
int cnt;
int n;
int dis[N];
int vis[N];
int maxn,maxlen;
void add(int u,int v,int val){
e[cnt]=v,w[cnt]=val,ne[cnt]=head[u],head[u]=cnt++;
}
void dfs(int u,int depth)
{
if(depth>maxlen){
maxn=u;
maxlen=depth;
}
for(int i=head[u];i!=-1;i=ne[i]){
int v=e[i];
if(!vis[v]){
vis[v]=1;
dis[v]=max(dis[v],depth+w[i]);
dfs(v,depth+w[i]);
vis[v]=0;
}
}
}
int main()
{
while(~scanf("%d",&n)){
cnt =0;
maxlen=-1;
for(int i=1;i<=n;i++) head[i]=-1,dis[i]=0;
for(int i=2;i<=n;i++){
int a,b;
scanf("%d%d",&a,&b);
add(i,a,b);
add(a,i,b);
}
int temp;
vis[1]=1;
dfs(1,0);
vis[1]=0,maxlen=-1,vis[maxn]=1,temp=maxn;
dfs(maxn,0);
vis[temp]=0,maxlen=-1,vis[maxn]=1,temp=maxn;
dfs(maxn,0);
vis[temp]=0;
for(int i=1;i<=n;i++){
printf("%d\n",dis[i]);
}
}
return 0;
}