树形dp实例-Orgrimmar

Orgrimmar

题目描述
"In my memory, the last time such a tragic farewell to a respected Horde leader was at the top of Thunder Bluff. That day, Mother Earth was crying for him too. "
"This time, it is the Shadow of the Horde who has left us. At this moment, the entire Horde is whispering affectionately for him. "
“Son of Sen’jin, leader of the Darkspear tribe, Warchief of the Horde - Vol’jin.”
Born in the cunning and vicious troll race, he spent his life explaining to the world what loyalty and faith are.
A dissociation set of an undirected graph is a set of vertices such that if we keep only the edges between these vertices, each vertex in the set is connected to at most one edge.
The size of a dissociation set is defined by the size of the set of vertices.
The maximal dissociation set of the graph is defined by the dissociation set of the graph with the maximum size.
Sylvanas has a connected undirected graph that has n vertex and n−1 edges, and she wants to find the size of the maximal dissociation set of the graph.
But since she just became the warchief of the Horde, she is too busy to solve the problem.
Please help her to do so.
输入描述
The input consists of multiple test cases.
The first line contains one integer T (1≤T≤10) denoting the number of test cases.
The following are T test cases.
For each test case, the first line contains one integer n (n≤500000), which is the number of vertices.
The following n−1 lines each contains two integers x and y denoting an edge between x and y.
It is guaranteed that the graph is connected.
输出描述
For each test case, output one line containing one integer indicating the answer.
Notes: In this problem, you may need more stack space to pass this problem. We suggest you to add the following code into your main function if you use C++.
int main() {
int size(512<<20);  // 512M
__asm__ ( "movq %0, %%rsp\n"::"r"((char*)malloc(size)+size));
// YOUR CODE
...
exit(0);
}

样例
输入 复制
2
5
1 2
2 3
3 4
4 5
10
1 2
2 4
3 2
5 3
6 4
7 5
8 3
9 8
10 7
输出 复制
4
7


题意;
给你n个点,n-1条边,让你选出一些点构成一个集合,对于集合里的这些点最多只有一条边,问你最多能选出多少点

树形dp三种状态:
1、f[u][0]对于当前结点u不选,那么其子节点就可以任意选择
2、f[u][1]对于当前结点u选,不选其子节点
3、f[u][2]对于当前结点u选择,仅选择一个子节点

状态转移:
假设u的某一子节点为v
f[u][0] += max(max(f[v][0],f[v][1]),f[v][2])//选择一个子节点最大的状态求和
f[u][1] += f[v][0] 同时加上自己
假设选择子节点vv
f[u][2] = sum(f[v][0]) - f[vv][0](减去前面加上的f[vv][0]) + f[vv][1] 同时加上自己,可以看出是找max(f[vv][1]-f[vv][0])

Code:

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 5e5 +10;
const int mod = 1e8;
int T;
vector<int> e[N];
int f[N][4];
void dfs(int u,int fa) {
	int mx1=0,mx2=0,mx3=0;
	for(auto i:e[u]) {
		if(i==fa) continue;
		dfs(i,u);
		mx1 += max(max(f[i][0],f[i][1]),f[i][2]);
		mx2 += f[i][0];
		mx3 = max(mx3,f[i][1]-f[i][0]);
	}
	f[u][0] = mx1;
	f[u][1] = mx2+1;
	f[u][2] = mx2+mx3+1;
}
int main() {
	int size(512<<20);  // 512M
	__asm__ ( "movq %0, %%rsp\n"::"r"((char*)malloc(size)+size));

	ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);

	scanf("%d",&T);
	while(T--) {
		int n;
		scanf("%d",&n);
		for(int i=1; i<=n; i++) e[i].clear(),f[i][0]=f[i][1]=f[i][2]=0;
		for(int i=1; i<n; i++) {
			int u,v;
			scanf("%d%d",&u,&v);
			e[u].push_back(v);
			e[v].push_back(u);
		}
		dfs(1,0);
		cout<<max(max(f[1][0],f[1][1]),f[1][2])<<endl;
	}

	exit(0);
	return 0;
}

/*

*/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值