傳送門html
先了解一下拓撲排序c++
那麼瞭解了以後咱們再來看一下這道題數組
看這個條件:spa
若是這趟車次停靠了火車站 x,則始發站、終點站之間全部級別大於等於火車站x 的都必須停靠。code
這個條件等價於每個沒有停靠的點的級別都小於停靠過的站點的級別htm
題目要求的是最少劃分的級別數blog
那麼咱們能夠考慮拓撲排序排序
對於一條路徑x1→x2,咱們在這裏面尋找沒有停靠的站點,而後從這個沒有停靠的站點向每個停靠過的站點連邊(注意開一個vis數組避免重邊),而後拓撲排序板子稍微改一下就能夠了get
#include<bits/stdc++.h> using namespace std; const int MAXN=3000010; const int maxn=1005; int head[MAXN],to[MAXN],nxt[MAXN]; int in[maxn],cnt,dep[maxn]; int a[maxn],flag[maxn],vis[maxn][maxn],ans; //flag標記是否停靠,vis去重邊 inline void add(int u,int v) { cnt++; to[cnt]=v; nxt[cnt]=head[u]; head[u]=cnt; }//鄰接鏈表存邊 int n,m; int main() { scanf("%d%d",&n,&m); for(int i=1;i<=m;i++) { memset(a,0,sizeof(a)); memset(flag,0,sizeof(flag)); int k; scanf("%d",&k); for(int j=1;j<=k;j++) { scanf("%d",&a[j]); flag[a[j]]=1;//標記 } for(int j=a[1]+1;j<=a[k];j++) { if(!flag[j]) { for(int p=1;p<=k;p++) { if(!vis[j][a[p]]) { in[a[p]]++; add(j,a[p]); vis[j][a[p]]=1; } } } } } queue<int> q; for(int i=1;i<=n;i++) { if(!in[i]) q.push(i),dep[i]=1; //剛開始入度就爲0的點深度爲1 } while(!q.empty()) { int top=q.front(); q.pop(); for(int e=head[top];e;e=nxt[e]) { int v=to[e]; dep[v]=max(dep[v],dep[top]+1); //這個不加max也能夠,由於下面的ans已經取過max了 //不過加上也沒問題 ans=max(ans,dep[v]);//更新答案 in[to[e]]--;//入度-- if(!in[to[e]]) q.push(to[e]); } } cout<<ans; }