题解 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;
}

题解 CF459E Pashmak and Graph

上一篇:turtle画太阳


下一篇:爬虫详解(六--一)scrapy框架简介和基础应用