旅行计划
luogu 1137
题目大意:
有一堆点,之间连接着一些边(有向),保证无环,现在要求出从任意地方出发到所有点的最长路(出发点不一定相同)
原题:
题目描述
小明要去一个国家旅游。这个国家有#NNN个城市,编号为111至NNN,并且有MMM条道路连接着,小明准备从其中一个城市出发,并只往东走到城市iii停止。
所以他就需要选择最先到达的城市,并制定一条路线以城市iii为终点,使得线路上除了第一个城市,每个城市都在路线前一个城市东面,并且满足这个前提下还希望游览的城市尽量多。
现在,你只知道每一条道路所连接的两个城市的相对位置关系,但并不知道所有城市具体的位置。现在对于所有的iii,都需要你为小明制定一条路线,并求出以城市iii为终点最多能够游览多少个城市。
输入输出格式
输入格式:
第111行为两个正整数N,MN, MN,M。
接下来MMM行,每行两个正整数x,yx, yx,y,表示了有一条连接城市xxx与城市yyy的道路,保证了城市xxx在城市yyy西面。
输出格式:
NNN行,第iii行包含一个正整数,表示以第iii个城市为终点最多能游览多少个城市。
输入输出样例
输入样例#1:
5 6
1 2
1 3
2 3
2 4
3 4
2 5
输出样例#1:
1
2
3
4
3
说明
均选择从城市111出发可以得到以上答案。
对于20%20\%20%的数据,N≤100N ≤ 100N≤100;
对于60%60\%60%的数据,N≤1000N ≤ 1000N≤1000;
对于100%100\%100%的数据,N≤100000,M≤200000N ≤ 100000,M ≤ 200000N≤100000,M≤200000。
解题思路:
用拓扑排序跑一便,顺便DP就可以了
代码(邻接表+手动队列):
#include<cstdio>
#define max(a,b) (a)>(b)?(a):(b)
using namespace std;
int n,m,x,y,h,w,t,tot,rd[100005],b[100005],head[100005],d[100005];
struct rec
{int to,next;
}a[200005];
void topsort()
{for (int i=1;i<=n;++i)if (!rd[i])d[++w]=i,b[i]=1;//入度为0t=1;while(t<=w){h=d[t];++t;for (int i=head[h];i;i=a[i].next){b[a[i].to]=max(b[a[i].to],b[h]+1);//DPrd[a[i].to]--;//入读减一if (!rd[a[i].to])d[++w]=a[i].to;//入队}}
}
int main()
{scanf("%d %d",&n,&m);for (int i=1;i<=m;++i){scanf("%d %d",&x,&y);a[++tot].to=y;a[tot].next=head[x];head[x]=tot;//连接rd[y]++;//入度加一}topsort();for (int i=1;i<=n;++i)printf("%d\n",b[i]);//输出
}
代码(邻接表+STL队列):
#include<queue>
#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
int n,m,x,y,h,tot,rd[100005],b[100005],head[100005];
struct rec
{int to,next;
}a[200005];
void topsort()
{queue<int>d;for (int i=1;i<=n;++i)if (!rd[i])d.push(i),b[i]=1;//入度为0while(!d.empty()){h=d.front();d.pop();for (int i=head[h];i;i=a[i].next){b[a[i].to]=max(b[a[i].to],b[h]+1);//DPrd[a[i].to]--;//入读减一if (!rd[a[i].to])d.push(a[i].to);//入队}}
}
int main()
{scanf("%d %d",&n,&m);for (int i=1;i<=m;++i){scanf("%d %d",&x,&y);a[++tot].to=y;a[tot].next=head[x];head[x]=tot;//连接rd[y]++;//入度加一}topsort();for (int i=1;i<=n;++i)printf("%d\n",b[i]);//输出
}