題解 CF459E Pashmak and Graph
阿新 • • 發佈:2021-08-01
這題是課上的例題。
可是今天再做卻仍然不會……
給定一張有向圖,求最長的邊權遞增路徑。
很快可以想到 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; }