题解 CF120F 【Spiders】

题外话:

这道题目的翻译有点小问题,翻译没有说要开文件,但是题目是要求开文件的!我因为这个错了一次,看到错误信息才会看题目发现要开文件:

freopen("input.txt","r",stdin);
freopen("output.txt","w",stdout);

这是应该开的文件

解题思路:

这道题的大意就是给我们(n)棵树,让我们任意合并这(n)棵树,问能得到的最大直径。很显然的贪心,就是我们每次都把直径拼接在一起,然后最后的答案其实就是(n)棵树的直径长度和,我们也根本不用模拟拼接的过程。

对于无根树找直径的方法:

有两种,一种是(两次BFSor两次DFS),一种是树形DP,这里介绍两次DFS版的

首先任意取一个节点(我是随机rand()了一个节点),进行一次DFS,找出离它最远的点假设为(p),然后再以(p)为起点进行一次DFS,找出离(p)最远的点(q),这时候,(p)(q)的路径形成的就是树的直径.

Code

#include <bits/stdc++.h>
using namespace std;
int T,n,p,v,m = 0;
struct Edge{
	int next,to;
}edge[10005];
int head[1000];
int deep[1005];
void add_edge(int from,int to)
{
	m ++;
	edge[m].to = to;
	edge[m].next = head[from];
	head[from] = m;
}

void DFS(int x,int from)
{
	deep[x] = deep[from] + 1;
	for(int i = head[x] ; i ; i = edge[i].next)
	{
		int to = edge[i].to;
		if(!deep[to])DFS(to,x);
	}
	return ;
}
int main()
{	
	freopen("input.txt","r",stdin);	
	freopen("output.txt","w",stdout);
	cin >> T;
	int ans = 0;
	
	while(T)
	{
		cin >> n;
		m = 0;
		memset(head,0,sizeof(head));
		memset(deep,0,sizeof(deep));
		for(int i = 1 ; i <= n-1; i ++)
		{
			int u,v;
			cin >> u >> v;
			add_edge(u,v);
			add_edge(v,u);
		}
		srand(time(NULL));
		int s = rand() % n + 1;
		DFS( s , 0 );
		for(int i = 1 ; i <= n ; i ++)
			if(deep[i] > deep[s]) s = i;//第一次DFS
		memset(deep,0,sizeof(deep));
		DFS( s , 0 );
		for(int i = 1 ; i <= n ; i ++)
			if(deep[i] > deep[s]) s = i;
		ans += deep[s] - 1;
        	//第二次DFS,因为起点深度默认为1,所以统计答案要-1
		T--;
	}
	
	cout << ans;
	return 0;
}
原文地址:https://www.cnblogs.com/MYCui/p/13869874.html