1. 程式人生 > 其它 >題解 CF459E Pashmak and Graph

題解 CF459E Pashmak and Graph

這題是課上的例題。
可是今天再做卻仍然不會……

給定一張有向圖,求最長的邊權遞增路徑。

很快可以想到 dp。
一開始的 dp 思路是對於沒一條邊,用起點的各個邊去更新終點。但是這樣複雜度是邊數的平方(菊花圖),漁神想出了化邊為點跑最短路的巧妙做法,遺憾的是,菊花圖照樣把建邊複雜度卡到平方。

邊太麻煩想用點來記錄狀態又得記錄到這個點的最後一條邊的權值,複雜度同樣是平方的。

然後就好好好打量打量這個 dp 了。用起點的各個邊去更新終點,這裡面只有比該點權值小的被使用了,也就是說,對於一條邊,圖上的其它部分不管怎麼搞,它的所有貢獻都來自和比它權值小的邊。
那麼按照邊權排序,按照這個順序來更新就可以了。

需要注意邊權可以重複,所以得先記錄所有的答案,到一塊相同的邊權處理完的時候再更新到 dp 數組裡去。
輸入規模大,得關流同步,因為這個 T 了一次。

程式碼
#include <iostream>
#include <algorithm>
#include <vector>
#include <utility>
const int M = 300005, N = M;
struct twt { int u, v, w; bool operator < (twt b) const { return w < b.w; }; };
std::vector<std::pair<int, int> > cha;
int n, m, f[N], ans;
twt e[M];
void sync() {
    for (int i = 0; i < (int)cha.size(); i++) {
        f[cha[i].first] = std::max(f[cha[i].first], cha[i].second);
        ans = std::max(ans, f[cha[i].first]);
    }
    cha.clear();
}
int main() {
    std::ios::sync_with_stdio(false), std::cin.tie(0), std::cout.tie(0);
    
    std::cin >> n >> m;
    for (int i = 1; i <= m; i++) 
        std::cin >> e[i].u >> e[i].v >> e[i].w;
    std::sort(e+1, e+1+m);
    for (int i = 1; i <= m; i++) {
        if (e[i].w != e[i-1].w) sync();
        cha.push_back(std::make_pair(e[i].v, f[e[i].u] + 1));
    } 
    sync();
    std::cout << ans;
}