码迷,mamicode.com
首页 > 其他好文 > 详细

nyoj 1208——水题系列——————【dp】

时间:2015-05-05 16:26:31      阅读:95      评论:0      收藏:0      [点我收藏+]

标签:

水题系列

时间限制: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\n",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;
}

  

nyoj 1208——水题系列——————【dp】

标签:

原文地址:http://www.cnblogs.com/chengsheng/p/4479239.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!