题目链接:
http://codeforces.com/problemset/problem/459/E
题意:
给一个n个点和m条带权值的有向边的图。保证无自环和重边。在图中找到最长的一条有向路径,使得路径中的边权是严格递增的,求路径的最大长度(路径中边的数量)。
思路:
要注意到边权只有10^5。如果直接在图上找的话太麻烦了,我们考虑先把边排序,然后依次一条一条边往图上加。
用dp[v]表示以v结尾的最长路径的长度。对于图中新增的一条边u→v,可以更新dp[v]=max(dp[v],dp[u]+1)。
但是考虑到路径要求是严格递增的,我们需要在同一时间把相同边权的边都加进图中,所以需要额外开一个数组,在边权相同时, tmp[v] = max(tmp[v],dp[u]+1),在所有的边加完了之后再更新: dp[v] = max(dp[v],tmp[v])
时间复杂度:O(n+mlog(m))
代码:
1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 #define MS(a) memset(a,0,sizeof(a)) 5 #define MP make_pair 6 #define PB push_back 7 const int INF = 0x3f3f3f3f; 8 const ll INFLL = 0x3f3f3f3f3f3f3f3fLL; 9 inline ll read(){ 10 ll x=0,f=1;char ch=getchar(); 11 while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} 12 while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} 13 return x*f; 14 } 15 ////////////////////////////////////////////////////////////////////////// 16 const int maxn = 3e5+10; 17 18 struct node{ 19 int u,v,w; 20 }a[maxn]; 21 22 int n,m; 23 24 bool cmp(node& a,node& b){ 25 return a.w < b.w; 26 } 27 28 int dp[maxn],tmp[maxn]; 29 30 int main(){ 31 cin >> n >> m; 32 for(int i=0; i<m; i++){ 33 scanf("%d%d%d",&a[i].u,&a[i].v,&a[i].w); 34 } 35 sort(a,a+m,cmp); 36 37 for(int i=0; i<m; i++){ 38 bool flag = 1; 39 int t = i; 40 while(i+1<m && a[i].w==a[i+1].w){ 41 int u=a[i].u,v=a[i].v,w=a[i].w; 42 tmp[v] = max(tmp[v],dp[u]+1); 43 // cout << v << " " << tmp[v] << " ??" << endl; 44 flag = 0; 45 i++; 46 } 47 if(!flag) { 48 int u = a[i].u,v = a[i].v,w = a[i].w; 49 tmp[v] = max(tmp[v],dp[u]+1); 50 // cout << v << " " << tmp[v] << " ??" << endl; 51 } 52 if(!flag) 53 for(int j=t; j<=i; j++){ 54 // cout << "gg" << endl; 55 int u=a[j].u,v=a[j].v,w=a[j].w; 56 dp[v] = max(dp[v],tmp[v]); 57 // cout << u << " " << tmp[u] << " ppp" << endl; 58 // cout << v << " " << dp[v] << " ==" << endl; 59 } 60 else{ 61 dp[a[t].v] = max(dp[a[t].v],dp[a[t].u]+1); 62 // cout << a[t].v << " " << a[t].u << " " << dp[a[t].v] << endl; 63 } 64 } 65 66 int ans = 0; 67 for(int i=1; i<=n; i++){ 68 // cout << i << " " << dp[i] << endl; 69 ans = max(ans,dp[i]); 70 } 71 cout << ans << endl; 72 73 return 0; 74 }