树形dp The Tree Root uva10459

树形dp,两次dfs

son1[u],节点u向下能访问到的最大深度

son2[u],节点u向下能访问到的次大深度

f[u],节点向上能访问到的最大深度

第一次dfs求得son数组

dfs(v,u);
			if(son1[v]+1 > son1[u]){
				son2[u] = son1[u];
				son1[u] = son1[v]+1;
			}
			else{
				son2[u] = max(son2[u],son1[v]+1);
			}

第二次dfs根据son数组求得f数组

if(son1[v]+1==son1[u]){
				f[v] = max(f[v],son2[u]+1);
			}
			else{
				f[v] = max(f[v],son1[u]+1);
			}
			f[v] = max(f[v],f[u]+1);
			dfs1(v,u);

这道题注意不要有重边,有重边的话,dfs的时候树就会被遍历不止一次是指数级别的,会t的

代码:

/********************************************
Author         :Crystal
Created Time   :
File Name      :
********************************************/
#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <climits>
#include <string>
#include <vector>
#include <cmath>
#include <stack>
#include <queue>
#include <set>
#include <map>
#include <sstream>
#include <cctype>
using namespace std;
typedef long long ll;
typedef pair<int ,int> pii;
#define MEM(a,b) memset(a,b,sizeof a)
#define CLR(a) memset(a,0,sizeof a);
const int inf = 0x3f3f3f3f;
const int MOD = 1e9 + 7;
#define LOCAL
#define maxn 10005
int cnt = 0;
int dp[maxn];
int f[maxn];
int son1[maxn];
int son2[maxn];
int head[maxn],pnt[maxn],nxt[maxn];
int v1[maxn];
int v2[maxn];
void addedge(int u,int v){
	pnt[cnt] = v;
	nxt[cnt] = head[u];
	head[u] = cnt++;
}
void dfs(int u,int f1){
	for(int i=head[u];~i;i=nxt[i]){
		int v = pnt[i];
		if(v!=f1){
			dfs(v,u);
			if(son1[v]+1 > son1[u]){
				son2[u] = son1[u];
				son1[u] = son1[v]+1;
			}
			else{
				son2[u] = max(son2[u],son1[v]+1);
			}
		}
	}
}
void dfs1(int u,int f1){
	for(int i=head[u];~i;i=nxt[i]){
		int v = pnt[i];
		if(v!=f1){
			if(son1[v]+1==son1[u]){
				f[v] = max(f[v],son2[u]+1);
			}
			else{
				f[v] = max(f[v],son1[u]+1);
			}
			f[v] = max(f[v],f[u]+1);
			dfs1(v,u);
		}
	}
}
int main()
{
#ifdef LOCAL
	freopen("in.txt", "r", stdin);
//	freopen("out.txt","w",stdout);
#endif
	int n;
	while(scanf("%d",&n)!=EOF){
		int a = 0;
		int b = 0;
		int nmax = -1;
		int nmin = inf;
		MEM(dp,-1);
		MEM(son1,-1);
		MEM(son2,-1);
		MEM(f,-1);
		MEM(head,-1);
		cnt = 0;
		for(int i=1;i<=n;i++){
			int t;scanf("%d",&t);
			for(int j=1;j<=t;j++){
				int v;scanf("%d",&v);
				addedge(i,v);
			}
		}
		dfs(1,-1);
		dfs1(1,-1);
		for(int i=1;i<=n;i++){
			dp[i] = max(f[i],son1[i]);
		}
		for(int i=1;i<=n;i++){
			nmax = max(dp[i],nmax);
			nmin = min(nmin,dp[i]);
		}
		for(int i=1;i<=n;i++){
			if(dp[i]==nmax){
				v1[a++] = i;
			}
			if(dp[i]==nmin){
				v2[b++] = i;
			}
		}
		sort(v1,v1+a);
		sort(v2,v2+b);
		printf("Best Roots  :");
		for(int i=0;i<b;i++){
			printf(" %d",v2[i]);
		}
		printf("\n");
		printf("Worst Roots :");
		for(int i=0;i<a;i++){
			printf(" %d",v1[i]);
		}
		printf("\n");
	}
	return 0;
}









你可能感兴趣的:(dp,树形DP)