1. 程式人生 > >Codeforces Round #261(Div 2) E Pashmak and Graph(圖中嚴格遞增的最長路徑、思維)

Codeforces Round #261(Div 2) E Pashmak and Graph(圖中嚴格遞增的最長路徑、思維)

題目連結

題意

給一個n個點和m條帶權值的有向邊的圖。保證無自環和重邊。在圖中找到最長的一條有向路徑,使得路徑中的邊權是嚴格遞增的,求路徑的最大長度(路徑中邊的數量)。

資料範圍:2n3105;1mmin(n(n1),3105),邊權105

分析

又是一道思維好題。
要注意到邊權只有105。如果直接在圖上找的話太麻煩了,我們考慮先把邊排序,然後依次一條一條邊往圖上加。用dp[v]表示以v結尾的最長路徑的長度。對於圖中新增的一條邊xy,可以更新dp[y]=max(dp[y],dp[x]+1)。但是考慮到路徑要求是嚴格遞增的,我們需要在同一時間把相同邊權的邊都加進圖中,所以需要額外開一個數組,在更新時新,tmp[y]=max(tmp[y],dp[x]+1)

,再所有的邊加完了之後再更新:dp[y]=max(dp[y],tmp[y])

時間複雜度:O(n+mlog(m))

Code

#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <math.h>
#include <vector>
#include <iostream>
using namespace std;
const int MAX_W = 100010;
const int MAX_N = 300010;

vector<pair<int
, int>
> w[MAX_W]; int n, m, dp[MAX_N], tmp[MAX_N]; int main() { ios_base::sync_with_stdio(0); cin.tie(0); cin >> n >> m; int Max = 0; for (int i = 0; i < m; ++i) { int u, v, len; cin >> u >> v >> len; w[len].push_back(make_pair(u, v)); Max = max(Max, len); } for
(int i = 1; i <= Max; ++i) { for (int j = 0; j < w[i].size(); ++j) { int u = w[i][j].first, v = w[i][j].second; tmp[v] = 0; } for (int j = 0; j < w[i].size(); ++j) { int u = w[i][j].first, v = w[i][j].second; tmp[v] = max(tmp[v], dp[u] + 1); } for (int j = 0; j < w[i].size(); ++j) { int u = w[i][j].first, v = w[i][j].second; dp[v] = max(dp[v], tmp[v]); } } int ans = 0; for (int i = 1; i <= n; ++i) { ans = max(ans, dp[i]); } cout << ans << endl; return 0; }