题目链接:
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;
}