zoukankan      html  css  js  c++  java
  • 洛谷P1137旅行计划(拓扑排序+简单dp)

    题目地址:https://www.luogu.com.cn/problem/P1137

    题目描述

    小明要去一个国家旅游。这个国家有N个城市,编号为1N,并且有M条道路连接着,小明准备从其中一个城市出发,并只往东走到城市i停止。

    所以他就需要选择最先到达的城市,并制定一条路线以城市i为终点,使得线路上除了第一个城市,每个城市都在路线前一个城市东面,并且满足这个前提下还希望游览的城市尽量多。

    现在,你只知道每一条道路所连接的两个城市的相对位置关系,但并不知道所有城市具体的位置。现在对于所有的i,都需要你为小明制定一条路线,并求出以城市i为终点最多能够游览多少个城市。

    输入

    1行为两个正整数N, M

    接下来MM行,每行两个正整数x, y,表示了有一条连接城市x与城市y的道路,保证了城市x在城市y西面。

    输出

    N行,第i行包含一个正整数,表示以第ii个城市为终点最多能游览多少个城市。

    题解:

    首先进行一个拓扑排序,找到这个拓扑排序,对这个拓扑排序进行dp。按照拓扑排序的顺序进行dp,当前dp值是指向它的结点的最大dp加1构成的

    AC代码:

    #include<bits/stdc++.h>
    using namespace std;
    const int N=1e5+10;
    const int M=2e5+10;
    int head[2][N]={0},cnt=0,n,m;
    int num[N];
    int r[N]={0};
    struct st{
        int from,to,next;
    }edge[2][M*2];//0:正图 1:反图 
    void addedge(int u,int v,int k){
        if(!k) cnt++;
        edge[k][cnt].from=u;
        edge[k][cnt].to=v;
        edge[k][cnt].next=head[k][u];
        head[k][u]=cnt;
    }
    void bfs(int s){
        queue<int>q;
        q.push(s);
        int cnt=0;
        while(!q.empty()){
            int st=q.front();q.pop();
            num[cnt++]=st;
            for(int i=head[0][st];i!=-1;i=edge[0][i].next){
                r[edge[0][i].to]--;
                if(r[edge[0][i].to]==0) q.push(edge[0][i].to);
            }
        } 
    }
    int main(){
        cin>>n>>m;
        memset(head,-1,sizeof(head));
        for(int i=1,u,v;i<=m;i++){
            cin>>u>>v;
            addedge(u,v,0);
            r[v]++;
            addedge(v,u,1);
        }
        for(int i=1;i<=n;i++) {
            addedge(0,i,0);
            r[i]++;
            addedge(i,0,1);
        }
        bfs(0);
        int dp[N]={0};
    //    for(int i=1;i<=n;i++) cout<<num[i]<<" ";cout<<endl; 
        for(int k=1;k<=n;k++){
            int i=num[k];
            for(int j=head[1][i];j!=-1;j=edge[1][j].next){
                dp[i]=max(dp[i],dp[edge[1][j].to]+1);
            }
            dp[i]=max(dp[i],1);
        }
        for(int i=1;i<=n;i++){
            cout<<dp[i]<<endl;
        } 
        return 0;
    }

    写于:2020/8/19 19:34


    作者:孙建钊
    出处:http://www.cnblogs.com/sunjianzhao/
    本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

  • 相关阅读:
    C++中使用多线程
    hdu 4223 dp 求连续子序列的和的绝对值最小值
    hdu 1372 bfs 计算起点到终点的距离
    hdu 4217 线段树 依次取第几个最小值,求其sum
    心得
    hdu 1175 bfs 按要求进行搜索,是否能到达,抵消两个(相同)棋子
    hdu 4221 greed 注意范围 工作延期,使整个工作时间罚时最少的单个罚时最长的值
    hdu 2844 多重背包 多种硬币,每一种硬币有一点数量,看他能组成多少种钱
    uva LCDDisplay
    hdu 4218 模拟 根据一个圆点和半径画一个圆 注意半径要求
  • 原文地址:https://www.cnblogs.com/sunjianzhao/p/13531421.html
Copyright © 2011-2022 走看看