题目描述:
小明要去一个国家旅游。这个国家有 N 个城市,编号为 1~N,并且有 M 条道路连接着,小明准备从其中一个城市出发,并只往东走到城市 i 停止。
所以他就需要选择最先到达的城市,并制定一条路线以城市 i 为终点,使得线路上除了第一个城市,每个城市都在路线前一个城市东面,并且满足这个前提下还希望游览的城市尽量多。
现在,你只知道每一条道路所连接的两个城市的相对位置关系,但并不知道所有城市具体的位置。现在对于所有的 i,都需要你为小明制定一条路线,并求出以城市 i 为终点最多能够游览多少个城市。
输入输出:
输入:
输入的第 1 行为两个正整数 N, M。
接下来 M 行,每行两个正整数 x,
y,表示了有一条连接城市 x 与城市 y 的道路,保证了城市 x 在城市 y 西面。
输出:
输出包括 N 行,第 i 行包含一个正整数,表示以第 i 个城市为终点最多能游览多少个城市。
题解:
由于只往东走,所以这是一个 DAG
DAG 上的最长路用 dp 解决
求拓扑序时 dp 求解最长路
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53
| #include <iostream> #include <cstdio> #include <cstring> #include <algorithm> using namespace std; const int Mn(100005); const int Mm(200005); struct edge { int e; edge* next; }*vr[Mn],Er[Mm]; edge *v[Mn],E[Mm]; int ans[Mn]; int topo[Mn]; int in[Mn]; int main() { int n,m; cin >> n >> m; for(int i(1);i<=m;++i) { int s,e; scanf("%d %d",&s,&e); ++in[e]; E[i].e=e, E[i].next=v[s]; v[s] = E+i; Er[i].e=s, Er[i].next=vr[e]; vr[e] = Er+i; } int h(1),t(1); for(int i(1);i<=n;++i) if(!in[i]) topo[t++] = i, ans[i] = 1; while(h!=t) { for(edge* e(v[topo[h]]);e;e=e->next) { --in[e->e]; if(!in[e->e]) { topo[t++] = e->e; for(edge* er(vr[e->e]);er;er=er->next) ans[e->e] = max(ans[e->e],ans[er->e]+1); } } ++h; } for(int i(1);i<=n;++i) cout << ans[i] << endl; return 0; }
|