Codeforces459 E. Pashmak and Graph(dp,同时转移)

题意:

给定n个点m条边的带权有向图,
要求找到一条最长路径,满足每条边的边权严格大于上一条边。
输出最长路径的长度。

数据范围:n,m<=3e5,保证无自环和重边

解法:

对边权排序
令d[i]为以点i为结尾的最长路径长度
设边E=(a,b,c)
显然d[b]=max(d[b],d[a]+1),因为边权排过序,显然可以这样转移

但是有边权相等的情况,这时候如果出现例如1->3,3->4的边权相等
那么进行d[3]=d[1]+1,d[4]=d[3]+1的时候,d[4]就会出现错误

一种方法是将边权相同的边取出来,将d[3]=d[1]+1,d[4]=d[3]+1改为:
dd[3]=d[1]+1,dd[4]=d[3]+1,即将d转移到dd上,这样就是让相同边权的边无序同时转移,
最后再将这些点的dd[]复制回d[]就行了

code:

#include<bits/stdc++.h>
using namespace std;
const int maxm=3e5+5;
struct Node{
    int a,b,c;
}e[maxm];
int d[maxm];//d[i]表示以点i结尾的最长路径
int dd[maxm];//temp
int temp[maxm];//stack
int n,m;
bool cmp(Node a,Node b){
    return a.c<b.c;
}
signed main(){
    cin>>n>>m;
    for(int i=1;i<=m;i++){
        int a,b,c;scanf("%d%d%d",&a,&b,&c);
        e[i]={a,b,c};
    }
    sort(e+1,e+1+m,cmp);
    for(int i=1;i<=m;i++){
        int j=i;
        int num=0;
        while(j<=m&&e[j].c==e[i].c){
            temp[++num]=j;
            j++;//边权相同
        }
        for(int k=1;k<=num;k++){//将d转移到dd中
            int a=e[temp[k]].a,b=e[temp[k]].b;
            dd[b]=max(dd[b],d[a]+1);
        }
        for(int k=1;k<=num;k++){//将dd复制回d
            int b=e[temp[k]].b;
            d[b]=dd[b];
        }
        i=j-1;
    }
    int ans=0;
    for(int i=1;i<=n;i++){
        ans=max(ans,d[i]);
    }
    cout<<ans<<endl;
    return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_44178736/article/details/107897750