很久以前的一道暑假集训的题,忘了补。
感觉就是思维建图,加拓扑排序。
未停靠的火车站,必然比停靠的火车站等级低,就可以以此来建边,此处注意用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 }