【洛谷 P1137 旅行计划】简单树形DP

题目链接:
https://www.luogu.org/problemnew/show/P1137
题意:
给你 N N N 个点, M M M 条边,所有边都是单向边而且不存在环路,求出以点 i i i 为终点能够经过的最长链点数。
题解:
如果是第一次接触树形DP,不妨先从简单的情况开始考虑,比如说就是一条直线:1->2->3->4, 现在记 F [ i ] F[i] F[i] 为以 i i i 为终点所经过的最长链点数,那么显然, F [ 4 ] = 1 F[4] = 1 F[4]=1,点4只有它本身, F [ 3 ] = 2 F[3] = 2 F[3]=2 F [ 2 ] = 3 F[2] = 3 F[2]=3, F [ 1 ] = 4 F[1] = 4 F[1]=4,不难想出, F [ t o ] = F [ f r o m ] + 1 F[to] = F[from] + 1 F[to]=F[from]+1。那么现在延伸一下,把他扩展到更复杂的图中。在复杂的图中,一个点可能与多个点相连,但是我们仍有 F [ t o ] = F [ f r o m ] + 1 F[to] = F[from] +1 F[to]=F[from]+1, 不过别忘了, F [ i ] F[i] F[i] 表示的是以 i i i 为终点所经过的最长链点数,要取最大值,因为有的路过来长,有的路过来短,所以 F [ t o ] = m a x ( F [ t o ] , F [ f r o m ] + 1 ) F[to] = max(F[to], F[from] + 1) F[to]=max(F[to],F[from]+1),也就是父节点从所有子节点里面选最大的那个。
代码:

#include<bits/stdc++.h>
#define INF 0x3f3f3f3f
#define pi 3.1415926
#define mp(x, y) make_pair(x, y)
#define vi vector<int>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> Pair;
const int MAX = 1e5 + 10;

struct edge {
	int nxt, to;
}e[MAX << 1];

int N, M;
int f[MAX];// F[i]为以i为终点所经过的最长链点数
int head[MAX], tot;//前向星

void add(int u, int v) {//前向星加边
	e[++tot].nxt = head[u];
	e[tot].to = v;
	head[u] = tot;
}

void dfs(int u) {//当前点为u
	if (f[u])return;//已经算过
	int flag = 0;//标记是否还有子节点
	for (int i = head[u]; i; i = e[i].nxt) {
		flag = 1;
		int son = e[i].to;
		dfs(son);
		f[u] = max(f[u], f[son] + 1);
	}
	if (!flag)f[u] = 1;
}

int main() {
	ios::sync_with_stdio(0);
	tot = 0;
	cin >> N >> M;
	for (int i = 0; i < M; i++) {
		int x, y;
		cin >> x >> y;
		add(y, x);
	}
	for (int i = 1; i <= N; i++) {
		dfs(i);
		cout << f[i] << endl;
	}
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值