小智的旅行(Bridge)51nod 提高组试题

luogu AC传送门(官方数据)

题目描述

小智最喜欢旅行了,这次,小智来到了一个岛屿众多的地方,有N座岛屿,编号为0到N-1,岛屿之间 由一些桥连接,可以从桥的任意一端到另一端,由于岛屿可能比较大,所以会出现一些桥连接的是同 一个岛屿,岛屿之间也可能有多座桥连接,每条桥有一个长度,小智有一个习惯,每次走过的桥都必 须严格比之前走的桥长度长,小智可以从任意一个岛屿出发,任意一个岛屿结束,现在小智想知道最 多能走过多少条桥?

输入格式

第一行两个数N和M,分别表示岛屿个数和桥的个数 接下来M行,每行三个数a,b,c,表示岛屿a和b之间由一条长度为c的桥连接。

输出格式

一个数表示最多经过的桥的数量

 

咋一看,这道题好像有点迷。从普通的最小生成树、最短路、DFS等似乎无法下手。于是,考虑DP。

首先,设计状态: 设 dp[i] 表示第 i 个点最多的边。那么,如果我们能够走某一条边,即有:

dp[u] = max( dp[u],  dp[v] + 1).      dp[v] = max(dp[v], dp[u] + 1);

问题来了,如何确保我们的边可以走?   建图似乎很麻烦。

所以,我们直接排序!

将边按从小到大排序,那么就可以保证依次递增,我们就可以走了。

上代码:

#include <bits/stdc++.h>
using namespace std;
#define N 1000010
#define isdigit(c) ((c) >= '0' && (c) <= '9')

inline int read(){
    int x = 0, s = 1;
    char c = getchar();
    while(!isdigit(c)){
        if(c == '-')s = -1;
        c = getchar();
    }
    while(isdigit(c)){
        x = (x << 1) + (x << 3) + (c ^ '0');
        c = getchar();
    }
    return x * s; 
}
inline int max(int a, int b){
    return a > b ? a : b; 
}

struct node{
    int u, v, w;
} t[N];
int dp[N], temp[N]; 

bool cmp(node a, node b){
    return a.w < b.w;
}


int main(){
    int n = read(), m = read();
    for(int i = 0;i < m; i++)
        t[i].u = read() + 1, t[i].v = read() + 1, t[i].w = read();
    sort(t, t + m, cmp);
    int last = -1;
    dp[0] = 1;
    for(int i = 0;i < m; i++){
        if(t[i].w != t[i + 1].w){
            for(int j = last + 1; j <= i; j++){
                int u = t[j].u, v = t[j].v;
                temp[u] = dp[u];
                temp[v] = dp[v];  /*注意存临时变量,对应其原始dp值,因为后面u和v都要更改*/
            }
            for(int j = last + 1;j <= i; j++){
                int u = t[j].u, v = t[j].v;
                dp[u] = max(dp[u], temp[v] + 1);
                dp[v] = max(dp[v], temp[u] + 1);
            }    
            last = i;
        }
    
    }
    int ans = -666;
    for(int i = 1;i <= n; i++) ans = max(ans, dp[i]);
    printf("%d\n", ans);
    return 0; 
}

猜你喜欢

转载自www.cnblogs.com/wondering-world/p/12896630.html
今日推荐