P1807 最长路
历程:
- 直接上记忆化 \(89pts\) (对于不可到达n的结点不应该考虑在下一个状态内)
- 并查集判断可达性WA(我是哪根筋抽了用并查集判断有向图的可达性?)
- 两次记忆化,一次用来判断可达性,一次求最长路AC
#include<iostream>
#include<cstring>
using namespace std;
const int N = 1510, M = 50010;
int h[N], e[M], ne[M], w[M], idx;
int n, m;
int f[N], st[N], p[N];
void add(int a, int b, int v){
e[idx] = b, ne[idx] = h[a], w[idx] = v, h[a] = idx ++;
}
int check(int u){
if(u == n) return 1;
if(st[u]) return p[u];
st[u] = 1;
for(int i = h[u]; i != -1; i = ne[i]){
int j = e[i];
p[u] = max(p[u], check(j));
}
return p[u];
}
int dfs(int u){
if(u == n){
st[n] = 1;
return 0;
}
if(st[u]) return f[u];
st[u] = 1;
for(int i = h[u]; i != -1; i = ne[i]){
int j = e[i];
if(p[j]) f[u] = max(f[u], w[i] + dfs(e[i]));
}
return f[u];
}
int main(){
memset(h, -1, sizeof h);
cin >> n >> m;
for(int i = 0; i < m; i ++){
int a, b, v;
cin >> a >> b >> v;
add(a, b, v);
}
p[n] = 1;
check(1);
memset(st, 0, sizeof st);
// for(int i = 1; i <= n; i ++) cout << i << "->" << "n : " << p[i] << endl;
dfs(1);
if(p[1]) cout << f[1];
else cout << -1;
return 0;
}