洛谷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/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

原文地址:https://www.cnblogs.com/sunjianzhao/p/13531421.html