51Nod 1274 DP

题目链接


题意:
给定一个 n m 条边的无向图,可能有重边和自环,问从任意一个点开始,任意一个点结束,每一条经过的边均只经过一次,且沿着路径边权严格递增,问这样的路径最长能包括多少条边?


思路:
很明显的最优子结构,考虑动态规划。

因为需保证路径边权严格递增,故可以先将所有边按边权从小到大进行排序,保证状态转移时无后效性,因边权需严格单调递增,故对于边权相同的边,因单独取出来一起转移。

故此题得解。


代码:

#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<vector>
using namespace std;
typedef long long ll;

const int A = 1e5 + 10;
class Gra{
public:
    int u,v,w;
    bool operator<(const Gra& rhs){
        return w < rhs.w;
    }
}G[A];
int n,m,dp[A],reg[A];

int main(){
    scanf("%d%d",&n,&m);
    for(int i=1 ;i<=m ;i++) scanf("%d%d%d",&G[i].u,&G[i].v,&G[i].w);
    sort(G+1,G+1+m);

    int last = 1;
    for(int i=1 ;i<=m ;i++){
        if(i==m || G[i].w < G[i+1].w){
            for(int j=last ;j<=i ;j++) reg[G[j].u] = dp[G[j].u],reg[G[j].v] = dp[G[j].v];
            for(int j=last ;j<=i ;j++){
                dp[G[j].u] = max(dp[G[j].u],reg[G[j].v]+1);
                dp[G[j].v] = max(dp[G[j].v],reg[G[j].u]+1);
            }
            last = i + 1;
        }
    }

    int ans = 0;
    for(int i=0 ;i<n ;i++) ans = max(ans,dp[i]);
    printf("%d\n",ans);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/wubaizhe/article/details/79901805