P1807 最长路

历程:

  1. 直接上记忆化 (89pts) (对于不可到达n的结点不应该考虑在下一个状态内)
  2. 并查集判断可达性WA(我是哪根筋抽了用并查集判断有向图的可达性?)
  3. 两次记忆化,一次用来判断可达性,一次求最长路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;
}
原文地址:https://www.cnblogs.com/tomori/p/13881567.html