HDU 3534 Tree (树形dp求树的直径)

Tree

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 1894    Accepted Submission(s): 620


 

Problem Description

In the Data structure class of HEU, the teacher asks one problem: How to find the longest path of one tree and the number of such longest path?

 

 

Input

There are several test cases. The first line of each case contains only one integer N, means there are N nodes in the tree. N-1 lines follow, each line has three integers w,v and len, indicate that there is one edge between node w and v., and the length of the edge is len.
 

 

 

Output

For each test case, output the length of longest path and its number in one line.

 

 

Sample Input

 

4 1 2 100 2 3 50 2 4 50 4 1 2 100 2 3 50 3 4 50

 

 

Sample Output

 

150 2 200 1

 题目大意 : 输入一个树, 输出该数的最大边长和拥有最大边长的数目

思路 : 如果单纯求树的直径的话, 可以用两次dfs解决, 但是这样只能求出直径,无法求出数目了, 要想连同数目一起求出来, 还得枚举所有的叶子, 这样肯定超时, 所以用树形dp, 在记录直径的同时记录数量。 记录直径的原理就是, 任取一点当根, 一直搜到底, 然后开始往上更新长度, 当碰到一个点有不止一条链的时候,开始更新他的长度即数量, 当出现新的最大长度, 数量就是两个点的数量之积, 如果长度和最大长度相同, 则加上他们二者数量的乘积

Accepted coded

#include
#include
using namespace std;

#define sc scanf
#define ls rt << 1
#define rs ls | 1
#define Min(x, y) x = min(x, y)
#define Max(x, y) x = max(x, y)
#define ALL(x) (x).begin(),(x).end()
#define SZ(x) ((int)(x).size())
#define MEM(x, b) memset(x, b, sizeof(x))
#define lowbit(x) ((x) & (-x))
#define P2(x) ((x) * (x))

typedef long long ll;
const int MOD = 1e9 + 7;
const int MAXN = 15;
const int INF = 0x3f3f3f3f;
inline ll fpow(ll a, ll b){ ll r = 1, t = a; while (b){ if (b & 1)r = (r*t) % MOD; b >>= 1; t = (t*t) % MOD; }return r; }

struct Edge
{
	int v, w, next;
}e[MAXN << 1];
int head[MAXN], n, k, cnt, ans;
int dis[MAXN], num[MAXN];
void init() {
	MEM(head, -1); cnt = k = 0;
	ans = -INF;
}
void add(int from, int to, int wi) {
	e[++cnt].v = to;
	e[cnt].w = wi;
	e[cnt].next = head[from];
	head[from] = cnt;
}
void dfs(int x, int fa) {
	dis[x] = 0, num[x] = 1;
	for (int i = head[x]; i != -1; i = e[i].next) {
		int vi = e[i].v;
		if (vi != fa) {
			dfs(vi, x);
			if (dis[x] + dis[vi] + e[i].w > ans) { // 最大长度的更新
				ans = dis[x] + dis[vi] + e[i].w;
				k = num[x] * num[vi];  
			}
			else if (dis[x] + dis[vi] + e[i].w == ans) // 相等时的更新
				k += num[x] * num[vi];
			if (dis[x] < dis[vi] + e[i].w) {  // 更新点和数量
				dis[x] = dis[vi] + e[i].w;
				num[x] = num[vi];
			}
			else if (dis[x] == dis[vi] + e[i].w) // 更新数量
				num[x] += num[vi];
		}
	}
}

int main()
{
	while (~sc("%d", &n)) {
		init();
		for (int i = 1; i < n; i++) {
			int ui, vi, wi;
			sc("%d %d %d", &ui, &vi, &wi);
			add(ui, vi, wi); add(vi, ui, wi);
		}
		dfs(1, 1);
		cout << ans << " " << k << endl;
	}
 	return 0;
}

 

你可能感兴趣的:(树)