zoukankan      html  css  js  c++  java
  • CF960F Pathwalks

    题目描述

    给定 (n) 个点 (m) 条边的有向图,可能不连通,可能有重边,也可能会有自环。求最长的路径(可以经过重复节点),使得这条路径的编号和权值都严格单调递增,其中编号指输入的顺序。路径的长度是指经过边的数量。

    输入格式

    第一行两个整数 (n,m)

    第二行到第 (m+1) 行,每行三个整数 (a,b,k),表示顶点 (a) 与顶点 (b) 有一条边相连,边权为 (k)

    输出格式

    一行一个整数,表示最长的路径的长度。

    (1leq n,m,w_ileq10^5)


    考虑直接dp,设(f_i)表示前(i)条边其中保留第(i)条边时的答案,那么有转移方程如下:

    [f_i=max_{j=1}^{i-1}f_j+1[k_j<k_i,b_j=a_i] ]

    直接做是(O(n^2))的,那么考虑优化。

    观察这个式子我们可以发现,我们需要维护(N)个数组,每次查询一个数组里的前缀最大值,往一个数组里插入一个数,那么这个东西可以用动态开点线段树实现。

    Code

    #include <iostream>
    #include <cstdio>
    #include <algorithm>
    #include <cstring>
    const int N = 1e5;
    using namespace std;
    struct edges
    {
        int u,v,w;
    }edge[N + 5];
    int n,m,f[N + 5],ans,rt[N + 5];
    struct Seg
    {
        int mx[N * 20 + 5],lc[N * 20 + 5],rc[N * 20 + 5],node_cnt;
        void ins(int &k,int l,int r,int x,int v)
        {
            if (!k)
                k = ++node_cnt;
            mx[k] = max(mx[k],v);
            if (l == r)
                return;
            int mid = l + r >> 1;
            if (x <= mid)
                ins(lc[k],l,mid,x,v);
            else
                ins(rc[k],mid + 1,r,x,v);
        }
        int query(int k,int l,int r,int x)
        {
            if (!k)
                return 0;
            if (r <= x)
                return mx[k];
            int mid = l + r >> 1;
            if (x <= mid)
                return query(lc[k],l,mid,x);
            else
                return max(query(lc[k],l,mid,x),query(rc[k],mid + 1,r,x));
        }
    }tree;
    int main()
    {
        scanf("%d%d",&n,&m);
        for (int i = 1;i <= m;i++)
            scanf("%d%d%d",&edge[i].u,&edge[i].v,&edge[i].w),edge[i].w++;
        ans = f[1] = 1;
        tree.ins(rt[edge[1].v],1,N + 1,edge[1].w,f[1]);
        for (int i = 2;i <= m;i++)
        {
            f[i] = 1;
            f[i] = tree.query(rt[edge[i].u],1,N + 1,edge[i].w - 1) + 1;
            ans = max(ans,f[i]);
            tree.ins(rt[edge[i].v],1,N + 1,edge[i].w,f[i]);
        }
        cout<<ans<<endl;
        return 0;
    }
    
  • 相关阅读:
    [Oracle工程师手记]如何收集 RMAN 工作时的 10046 trace
    [Linux]Linux环境,如何查找一个目录下所有包含特定字符串的文件
    [Oracle工程师手记]如何找到 RMAN 的所有 session
    PowerShell提交HTTP Request Post请求
    PowerShell计算字符串MD5 Hash值
    《异类》笔记
    《哈弗商学院 判断与决策心理学课》笔记
    《影响力》笔记
    《金字塔原理》笔记
    三月十九日,偶感
  • 原文地址:https://www.cnblogs.com/sdlang/p/13993860.html
Copyright © 2011-2022 走看看