大臣的旅費(求樹的最遠點對,即樹的直徑)

題目大意:求樹上兩點的最遠距離。


分析:可以用DP解,也可以用兩次DFS。這裏我用兩次DFS,樹上最遠的點對一定是樹的直徑,而且樹上其他點到樹的直徑某一端點肯定是最遠的,第一遍搜找到直徑的某個端點,第二次就可以找出來樹的直徑了,然後就找到了最遠的點對啦。關鍵在於,理解樹上任意一點搜一次的最遠點一定在直徑的某個端點上。


Code:

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;

const int maxn = 100000;

struct node{
	int next;
	int to;
	int w;
}edge[maxn];

int n, cnt, x, maxx;
int head[maxn];
bool vis[maxn];

void dfs(int a, int sum) {
	if(maxx < sum) {
		maxx = sum;
		x = a;
	}
	for(int i = head[a]; ~i; i = edge[i].next) {
		int t = edge[i].to;
		if(!vis[t]) {
			vis[t] = true;
			dfs(t, sum+edge[i].w);
			vis[t] = false;
		}
	}
}

int main() {
	while(~scanf("%d", &n)) {
		memset(head, -1, sizeof(head));
		for(int i = 0; i < n-1; i++) {
			int a, b, c;
			scanf("%d%d%d", &a, &b, &c);
			edge[i].to = b-1;
			edge[i].next = head[a-1];
			edge[i].w = c;
			head[a-1] = i;
			edge[n-1+i].to = a-1;
			edge[n-1+i].next = head[b-1];
			edge[n-1+i].w = c;
			head[b-1] = n-1+i;
		}
		x = maxx = 0;
		memset(vis, 0, sizeof(vis));
		vis[0] = true;
		dfs(0, 0);
		vis[0] = false;
		memset(vis, 0, sizeof(vis));
		vis[x] = true;
		dfs(x, 0);
		printf("%d\n", maxx*(11+10+maxx)/2);
	}
	return 0;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章