我的Data Structures and Algorithms代码仓:https://github.com/617076674/Data-Structures-and-Algorithms
原题链接:https://pintia.cn/problem-sets/16/problems/674
题目描述:
知识点:关键路径
思路:SPFA算法
把所有边的边权乘以-1,令其变为相反数,再用SPFA算法求最短路径长度,将所得结果取反即可。
注意点:
题给的图不一定是一个连通图,对每一个连通分量中入度为0的点都需要用SPFA求解一次,再取每个连通分量中的最长路径。
时间复杂度是O(kM * s),其中M为图中的有向边数量,s为入度为0的点的数量。空间复杂度是O(N + M)。
C++代码:
#include<iostream>
#include<vector>
#include<queue>
using namespace std;
struct node {
int v;
int len;
node(int _v, int _len) {
v = _v;
len = _len;
}
};
int N, M, INF = 1000000000;
vector<node> graph[100];
int d[100], countInq[100], inDegree[100];
bool inq[100], visited[100];
int maxLen = 0;
bool spfa(int s);
int main() {
scanf("%d %d", &N, &M);
fill(inDegree, inDegree + N, 0);
int v1, v2, len;
for(int i = 0; i < M; i++) {
scanf("%d %d %d", &v1, &v2, &len);
graph[v1].push_back(node(v2, -len));
inDegree[v2]++;
}
bool flag = false;
for(int i = 0; i < N; i++) {
if(inDegree[i] == 0) {
flag = true;
}
}
if(!flag) {
printf("Impossible\n");
return 0;
}
for(int j = 0; j < N; j++) {
if(inDegree[j] != 0) { //SPFA的起点应该是入度为0的点
continue;
}
fill(visited, visited + N, false);
bool flag = spfa(j);
if(!flag) {
printf("Impossible\n");
return 0;
}
int tempMaxLen = 0;
for(int i = 0; i < N; i++) {
if(!visited[i]){ //如果没被访问过,说明不属于当前连通分量
continue;
}
if(tempMaxLen < -d[i]) {
tempMaxLen = -d[i];
}
}
maxLen = max(tempMaxLen, maxLen);
}
printf("%d\n", maxLen);
return 0;
}
bool spfa(int s) {
fill(d, d + 100, INF);
fill(countInq, countInq + 100, 0);
fill(inq, inq + 100, false);
d[s] = 0;
queue<int> q;
q.push(s);
visited[s] = true;
inq[s] = true;
countInq[s]++;
while(!q.empty()) {
int u = q.front();
q.pop();
inq[u] = false;
for(int i = 0; i < graph[u].size(); i++) {
int v = graph[u][i].v;
int len = graph[u][i].len;
if(d[u] + len < d[v]) {
d[v] = d[u] + len;
if(!inq[v]) {
q.push(v);
visited[v] = true;
inq[v] = true;
countInq[v]++;
if(countInq[v] > N - 1) {
return false;
}
}
}
}
}
return true;
}
C++解题报告: