2020 8.3树的直径练习

树的直径,又称树的构 长链。 我们将丆 棵树 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;
}

 

 

©️2020 CSDN 皮肤主题: 技术工厂 设计师:CSDN官方博客 返回首页