问题 J: 最长路径
传送门:ZWGOJ | eolymp's basecamp 11452
题目描述
原题面
There is a directed graph \(G\) with \(n\) vertices and \(m\) edges. The vertices are numbered \(1, 2, ..., n\), and for each \(i\:(1 \le i \le m)\), the \(i\)-th directed edge goes from vertex \(x_i\) to vertex \(y_i\).
\(G\:\) does not contain directed cycles.
Find the length of the longest directed path in \(G\). Here, the length of a directed path is the number of edges in it.
输入要求
The first line contains two integers: number of vertices \(n\:(2 \le n \le 10^5)\) and number of edges \(m\:(1 \le m \le 10^5)\). Each of the next \(m\) lines contains two integer \(x_i, y_i\:(1 \le x_i, y_i \le n)\) that describe the edge of the graph.
输出要求
Print the length of the longest directed path in \(G\).
样例
解法
解法和时间复杂度: (1)
- 此处时间复杂度为该解法的算法部分的时间复杂度,不是严谨的整题的时间复杂度
- 法1:拓扑排序 + 动态规划 \(O(n)\)
- 法2:最短路 - SPFA 算法 \(O(mn^2)\)
法1:拓扑排序 + 动态规划
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33 | #include <bits/stdc++.h>
#define int long long int
using namespace std;
const int MAXn = 2e5 + 9;
vector<int> g[MAXn];
int rd[MAXn], dp[MAXn];
queue<int> q;
signed main() {
int n, m;
scanf("%lld%lld", &n, &m);
for(int i = 1, u, v; i <= m; i ++) {
scanf("%lld%lld", &u, &v);
u ++; v ++;
g[u].push_back(v);
rd[v] ++;
}
for(int i = 1; i <= n; i ++)
if(!rd[i]) q.push(i);
int ans = 1;
while(!q.empty()) {
int now = q.front();
q.pop();
for(int next : g[now]) {
rd[next] --;
if(!rd[next]) q.push(next);
dp[next] = max(dp[next], dp[now] + 1);
ans = max(ans, dp[next]);
}
}
printf("%lld", ans);
return 0;
}
|
法2:最短路 - SPFA 算法
读入每条边的值,并记为其负值。使用 SPFA 等可以在负权图中寻找最短路的算法找到图中最短路,并输出路径长度的负值。
由于 SPFA 等算法只能寻找单源最短路,因此需要再从每个点出发,跑一遍 SPFA 等算法,时间复杂度较高,不能通过。
以下提供类似题目 P1807 最长路,只需要求出某两点之间的路径中最长的路径,使用 SPFA 算法,按照上述思路的实现。(该题亦可使用 拓扑排序 + 动态规划 的方式实现)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40 | #include <bits/stdc++.h>
#define int long long int
using namespace std;
typedef pair<int, int> pii;
const int MAXn = 1000 + 9;
vector<pii> g[MAXn];
int dis[MAXn];
bool ved[MAXn];
queue<int> q;
signed main() {
for(int i = 0; i <= MAXn - 3; i ++) dis[i] = LLONG_MAX;
int n, m;
scanf("%lld%lld", &n, &m);
for(int i = 1, u, v, w; i <= m; i ++) {
scanf("%lld%lld%lld", &u, &v, &w);
g[u].push_back({v, -w});
}
dis[1] = 0;
q.push(1);
ved[1] = true;
while(!q.empty()) {
int now = q.front();
q.pop();
ved[now] = false;
for(pii x : g[now]) {
int nxt = x.first;
if (dis[nxt] > dis[now] + x.second) {
dis[nxt] = dis[now] + x.second;
if (!ved[nxt]) {
q.push(nxt);
ved[nxt] = true;
}
}
}
}
dis[n] == LLONG_MAX ? printf("-1") : printf("%lld", -dis[n]);
return 0;
}
|