很久以前的一道暑假集训的题,忘了补。
感觉就是思维建图,加拓扑排序。
未停靠的火车站,必然比停靠的火车站等级低,就可以以此来建边,此处注意用vis来维护一下,一个起点和终点只建立一条边,因为不这样的话会重复建边。
虽然重复建边拓扑排序的时候,统计入度,更新入度的时候完全不影响结果,因为这个重复的点和入度都统计了,也都会在拓扑的删去,答案依然正确。
但是重复建边vector会弄的很大,导致MLE(我debug好久才发现MLE的原因)。洛谷上只能get到80分,加了vis就100了。
主要是思维吧,未经过的点向经过点建边,拓扑找每个点所属的层数,最后统计答案即可。
代码如下:
1 #include <bits/stdc++.h>
2 #define debug(x) cout << #x << ": " << x << endl
3 using namespace std;
4 typedef long long ll;
5
6 const int MAXN=1024;
7 const int INF=0x3f3f3f3f;
8 const int MOD=1e9+7;
9
10 int in[MAXN],lv[MAXN],stay[MAXN];
11 bool is[MAXN];
12 bool vis[MAXN][MAXN];
13 vector<int> to[MAXN];
14 int n,m;
15 queue<int> q;
16
17 void topsort()
18 {
19 for(int i=1;i<=n;++i)
20 {
21 if(!in[i])
22 {
23 q.push(i);
24 lv[i]=1;
25 }
26 }
27 while(!q.empty())
28 {
29 int u=q.front();q.pop();
30 for(auto v:to[u])
31 {
32 in[v]--;
33 if(in[v]==0)
34 {
35 q.push(v);
36 lv[v]=lv[u]+1;
37 }
38 }
39 }
40 }
41
42 int main()
43 {
44 ios::sync_with_stdio(false);
45 cin.tie(0);
46 cin>>n>>m;
47 while(m--)
48 {
49 int s;
50 cin>>s;
51 memset(is,0,sizeof(is));
52 for(int i=1;i<=s;++i)
53 {
54 cin>>stay[i];
55 is[stay[i]]=true;
56 }
57 for(int i=stay[1];i<=stay[s];++i)
58 {
59 if(!is[i])
60 {
61 //debug(i);
62 for(int j=1;j<=s;++j)
63 {
64 int u=stay[j];
65 if(!vis[u][i])
66 {
67 vis[u][i]=1;
68 to[i].push_back(u);
69 in[u]++;
70 }
71 }
72 }
73 }
74 }
75 // for(int i=1;i<=n;++i)
76 // debug(in[i]);
77 topsort();
78 int ans=0;
79 for(int i=1;i<=n;++i)
80 {
81 // debug(lv[i]);
82 ans=max(ans,lv[i]);
83 }
84 cout<<ans<<endl;
85 return 0;
86 }