【洛谷P1137】旅行计划【拓扑排序】

题目描述

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

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

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

输入格式

第11行为两个正整数N, MN,M。

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

输出格式

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

输入输出样例

输入 #1

5 6
1 2
1 3
2 3
2 4
3 4
2 5

输出 #1

1
2
3
4
3

分析&说明:

这道题用拓扑排序。每个点的答案是它所有前驱节点的答案加1,即f[i]=max(f[i],f[j]+1); 用邻接表存图,在拓扑排序(算一点模板)同时做一点小DP就好了。

CODE:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>  //STL队列
using namespace std;
int n,m,dis[100010],in[100010],tot,f[100010];
queue<int>q;  //创建队列
struct node{
    int to,next;
}a[400010];
int main()
{
	ios::sync_with_stdio(false);
    cin>>n>>m;
    for(int i=1;i<=m;i++)
    {
        int x,y;
        ios::sync_with_stdio(false);
        cin>>x>>y;
        a[++tot].to=y;  //邻接表
        a[tot].next=dis[x];
        dis[x]=tot;
        in[y]++;
    }
    for(int i=1;i<=n;i++)
    if(!in[i])
    {  //拓扑排序部分
        f[i]=1;
        q.push(i);
    }
    while(!q.empty())
    {
        int cnt=q.front();q.pop();
        memset(in,0,sizeof(in));
        for(int i=dis[cnt];i;i=a[i].next)
        {
            f[a[i].to]=max(f[a[i].to],f[cnt]+1);  //前驱节点+1
            if(!--in[a[i].to])
			q.push(a[i].to);    
        }   
    }
    for(int i=1;i<n;i++) 
	cout<<f[i]<<endl;  //特别注意输出
	cout<<f[n];
}
发布了35 篇原创文章 · 获赞 22 · 访问量 586

猜你喜欢

转载自blog.csdn.net/dgssl_xhy/article/details/104024183