zoukankan      html  css  js  c++  java
  • nyoj 1208——水题系列——————【dp】

    水题系列

    时间限制:1000 ms  |  内存限制:65535 KB
    难度:2
     
    描述
        给你一个有向图,每条边都有一定的权值,现在让你从图中的任意一点出发,每次走的边的权值必须必上一次的权值大的情况下,问你最多能走几条边?
     
    输入
    首先一个n和m,分别表示点的数目和边的数目
    接下来m行,每行三个值x,y,val,表示x到y有路,其权值为val。(1<n,m,val<10^5,0<x,y<=n)
    输出
    输出最多有的边的数目
    样例输入
    3 3
    1 2 1
    2 3 1
    3 1 1
    6 7
    1 2 1
    3 2 5
    2 4 2
    2 5 2
    2 6 9
    5 4 3
    4 3 4
    样例输出
    1
    6



    解题思路:这个题目刚看起来好像是图论,但是出题人是考察的dp思想。定义两个数组dp[i],g[i]分别表示边编号为i时的最多有向边及点为i时的最多有向边数目。转移方程为:
          如果边权不相同:dp[i]=g[E[i].st]+1,g[E[i].en]=max(g[E[i].en],dp[i])。
          如果边权相同:{i,i+1,i+2,i+3...}边集合中都为边权相同的边编号。
                 dp[i]=g[E[i].st]+1,dp[i+1]=g[E[i+1].st]+1,etc...
                 g[E[i].en]=dp[i],g[E[i+1].en]=dp[i+1],etc...
                 对于边权相同的情况,第一组样例可以看出问题,这里这种操作学长说是延迟,具体说应该是对点延迟,对边提前。


    #include<bits/stdc++.h>
    using namespace std;
    const int maxe=1e5+10;
    struct edge{
        int st,en;
        int val;
    }E[maxe];
    int dp[maxe],g[maxe];
    int INF=1e9;
    bool cmp(edge a,edge b){
        return a.val<b.val;
    }
    void solve(int n,int m){
        memset(dp,0,sizeof(dp));
        memset(g,0,sizeof(g));
        for(int i=0;i<m;i++){
            if(E[i].val<E[i+1].val){
                dp[i]=g[E[i].st]+1;
                g[E[i].en]=max(g[E[i].en],dp[i]);
            }else{
                int j,t=i;
                for( j=i;j<m;j++){
                    if(E[j].val!=E[j+1].val)
                        break;
                }
                i=j;
                for(int k=t;k<=j;k++){
                    dp[k]=g[E[k].st]+1;
                }
                for(int k=t;k<=j;k++){
                    g[E[k].en]=max(g[E[k].en],dp[k]);
                }
            }
        }
        int max_e=0;
    //    for(int i=1;i<=n;i++){        //遍历点跟边应该是相同的效果,但是后台的测试数据不过。。。
    //        if(g[i]>max_e){
    //            max_e=g[i];
    //        }
    //    }
            for(int i=0;i<m;i++){
                if(max_e<dp[i]){
                    max_e=dp[i];
                }
            }
        printf("%d
    ",max_e);
    }
    int main(){
        freopen("In.txt","r",stdin);
        freopen("OUT1.txt","w",stdout);
        int n,m;
        while(scanf("%d%d",&n,&m)!=EOF){
            for(int i=0;i<m;i++){
                scanf("%d%d%d",&E[i].st,&E[i].en,&E[i].val);
            }
            sort(E,E+m,cmp);
            E[m].val=INF;
            solve(n,m);
        }
        return 0;
    }
    

      

  • 相关阅读:
    发现不错的cache系统Cache Manager Documentation
    List.Sort用法
    Database Initialization Strategies in Code-First:
    git rebase
    osharpV3数据库初始化
    IdentityDbContext
    AspNetUsers
    VS2015 推荐插件
    ELMAH日志组件数据库脚本
    C#如何把List of Object转换成List of T具体类型
  • 原文地址:https://www.cnblogs.com/chengsheng/p/4479239.html
Copyright © 2011-2022 走看看