【CF459E】Pashmak and Graph(递推+动规)

f[i]表示以边i结尾的最长路径,g[i]表示以点i结尾的最长路径,f[i]=g[e[i].u]+1。注意特判边权相等的情况,每次更新边连接的出度点的g即可。

推的话,数据范围3e5所以想到dp,而且必须是一维,固定一维枚举一维。所以边权排个序,枚举时就不用管边权递增的约束条件,只需要特判下相等的情况。状态和动态转移方程还是比较神仙(对我这种蒟蒻来说),拿结尾边和点做状态,学到就是赚到。

#include<bits/stdc++.h>
#define ri register int
#define ll long long
#define For(i,l,r) for(ri i=l;i<=r;i++)
#define Dfor(i,r,l) for(ri i=r;i>=l;i--)
using namespace std;
const int M=300005;
int n,m,cnt,f[M],g[M],t=1,ans;
struct node{
    int u,to,w;
    bool operator <(const node&x)const{
        return w<x.w;
    }
}e[M];
inline ll read(){
    ll f=1,sum=0;
    char ch=getchar();
    while(!isdigit(ch)){if(ch==‘-‘)f=-1;ch=getchar();}
    while(isdigit(ch)){sum=(sum<<1)+(sum<<3)+(ch^48);ch=getchar();}
    return f*sum;
}
inline bool cmp(node x,node y){return x.w<y.w;}
int main(){
    n=read(),m=read();
    For(i,1,m){
        e[i].u=read(),e[i].to=read(),e[i].w=read();
    }
    sort(e+1,e+m+1,cmp);
    For(i,1,m){
        f[i]=g[e[i].u]+1;
        if(e[i].w!=e[i+1].w){
            For(j,t,i){
                g[e[j].to]=max(g[e[j].to],f[j]);//当前的下一个点是由连接它的边推来的
            }
            t=i+1;
        }
    }
    For(i,1,m) ans=max(ans,f[i]);
    printf("%d",ans);
    return 0;
}

原文地址:https://www.cnblogs.com/jian-song/p/11768212.html

时间: 2024-12-11 18:33:47

【CF459E】Pashmak and Graph(递推+动规)的相关文章

CF459E Pashmak and Graph【贪心+dp】

题目:CF459E Pashmak and Graph 题意:给出n个点,m条边的图,然后让你每次只能向权值更大边走,求最大的边数.可以走多次 分析:由于点比较多,我们可以先对权值从小到大排序,然后从小的开始,更新它的到的节点的值为前一个节点值+1,但是还会出现权值相等成环的情况,所以我们可以对相等的先不更新,保存起来,等相等的结束了再更新. 代码: #include<cstdio> #include<algorithm> using namespace std; const in

POJ 1737 Connected Graph 递推

题目大意:求n个点能组成多少种无向连通图 多年的老心病终于干掉了- - 令f[i]表示i个点能组成多少种无向图 首先易知我们能生成2^(i*(i-1)/2)种图 但是一些是不合法的 我们要将不合法的干掉 枚举1号节点与多少个点连通 设1号节点所在联通块大小为j(1<=j<=i-1) 那么与1相连的其它点有C(i-1,j-1)中选法,1号节点所在联通块有f[j]种连法,不与1号节点相连的点有2^((i-j)*(i-j-1)/2)种连法 故得到递推式f[i]=2^(i*(i-1)/2)-Σ[1&l

动规,模拟,递推,最长公共子序列

题目链接:http://poj.org/problem?id=1458 解题报告: 1.用二维数组模拟两个字符串上每个子串对应的最长公共子序列. 2.显然,就是要求二维数组最右下的数字 3.递推公式: if(s1[i-1]==s2[j-1]) maxlen[i][j]=maxlen[i-1][j-1]+1; else maxlen[i][j]=max(maxlen[i][j-1],maxlen[i-1][j]); Memory: 1024KTime: 0MSLanguage: C++Result

百练2755 神奇的口袋 【深搜】or【动规】or【普通递归】or【递推】

总Time Limit:  10000ms  Memory Limit:  65536kB 有一个神奇的口袋,总的容积是40,用这个口袋可以变出一些物品,这些物品的总体积必须是40.John现在有n个想要得到的物品,每个物品的体积分别是a1,a2--an.John可以从这些物品中选择一些,如果选出的物体的总体积是40,那么利用这个神奇的口袋,John就可以得到这些物品.现在的问题是,John有多少种不同的选择物品的方式. Input 输入的第一行是正整数n (1 <= n <= 20),表示不

hdu(1078)——FatMouse and Cheese(递推型动归)

题意: 现在有n*n的方块,然后每个方块中都有一个值,代表这个方块中含有奶酪的数量. 现在那个老鼠站在(0,0)点,并且它每次最多走k步,然后每次走到一个点,它都能获得那个点上含有的值,但是要保证它下次走到的点含有的奶酪数必须多于它现在在的那个位置上的奶酪数量. 思路: 这道题也是一道递推性动归,和poj 1088 滑雪那题的区别就是这题最多可以走k步. 这道题让我更加深刻的理解了递推性动归. #include<stdio.h> #include<string.h> #includ

poj(1088)——滑雪(经典递推型动归)

题意: 中文题,就是在所有的点中找一个点作为起点,然后叫你找出从起点开始的最长路径是多少. 这里高度必须严格递减. 思路: 一开始我碰到这题时,没有思路,是看题解写的. 但是今天我回头再去看时,发现自己能够独立写出来了,而且和上次的方法不一样.也许这就是进步吧! 其实就是一个递推型动归,如果理解了上一题,那么这题也好做了. 这是第一次写的: #include<stdio.h> #include<string.h> #include<iostream> #include&

【Java】【高精度】【组合数】【递推】poj1737 Connected Graph

http://blog.csdn.net/sdj222555/article/details/12453629 这个递推可以说是非常巧妙了. import java.util.*; import java.io.*; import java.math.*; public class Main{ static BigInteger[] g=new BigInteger[60]; static BigInteger[] f=new BigInteger[60]; static BigInteger[

POJ 1737 Connected Graph (大数+递推)

题目链接: http://poj.org/problem?id=1737 题意: 求 \(n\) 个点的无向简单连通图的个数.\((n<=50)\) 题解: 这题你甚至能OEIS. http://oeis.org/A001187 但不支持这样做.TAT 间接做. 总方案数减去不合法方案. 因为\(n\)个点的完全图有 \(C(n,2)={n(n-1) \over 2}\) 条边,显然就有 \(2^{C(n,2)}\) 种子图,即枚举每条边是否选择. 设$ f[i]$ 表示每个点都和点 \(1\)

[sdut]2879计数dp……或者递推

第五届省赛C:colourful cupcakes N=60. 天真如我,居然在考虑搜索的算法/(ㄒoㄒ)/~~三叉树……3^60=10^24+……不计算考虑复杂度都是耍流氓>_< 再算了一下,感觉O(N^4)可以试试,60^4=10^8+……但是毕竟最差的情况嘛>_<,再看一下题解果然是4重循环的……计数……dp……(想到之前坚信的搜索不禁(*/ω\*)) 中间看到了一个三次动规六个方程的算法. 做麻烦了. 学长思路好快. #include<iostream> #in