这道题可以暴力可以拓扑排序
甚至还可以差分约束????
原谅我一开始没看出来可以差分约束
这是暴力做法
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 using namespace std; 5 int f[1010][1010], a[1010];//f数组记录每趟车次停靠的站点,a数组记第i个车站的分级 6 bool by[1010][1010];//表示第i趟车是否在j站停靠,true表示停靠 7 int n, m, maxn; 8 int main(){ 9 cin>>n>>m; 10 memset(by,false,sizeof(by)); 11 for(int i=1; i<=n; i++){ 12 a[i]=1; 13 } 14 for(int i=1; i<=m; i++){ 15 cin>>f[i][0]; 16 for(int j=1; j<=f[i][0]; j++){ 17 cin>>f[i][j]; 18 by[i][f[i][j]]=true; 19 } 20 } 21 while(1){ 22 bool judge=false; 23 for(int i=1; i<=m; i++){ 24 maxn=0; 25 for(int j=f[i][1]; j<=f[i][f[i][0]]; j++){ 26 if(by[i][j]==false) maxn=max(a[j], maxn);//记录不停靠的最大值 27 } 28 maxn++;//停靠的一定比不停靠的至少打1 29 for(int j=1; j<=f[i][0]; j++){ 30 if(a[f[i][j]]<maxn){ 31 a[f[i][j]]=maxn; 32 judge=true; 33 } 34 } 35 } 36 if(!judge) break;//没有更新过就跳出 37 } 38 maxn=0; 39 for(int i=1; i<=n; i++){ 40 maxn=max(a[i],maxn); 41 } 42 cout<<maxn<<endl; 43 return 0; 44 }
这是拓扑的做法
把没有停靠过的车站连一条有向边到停靠过的车站。没有停靠过的从下面向上指向停靠过的,等级比上面的低。
那么每有一层就代表有一个等级,不断地断边,每断掉一层就ans++
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 using namespace std; 5 int s[1005], degree[1005], topo[1005];//s记录停靠的车站,degree表示类似于入度的东西,topo为记录数组 6 bool is[1005], edge[1005][1005], vis[1005];//is表示是否停靠,edge表示是否从i到j连边, vis表示是否在topo数组里 7 int n, m, ans, top; 8 int main(){ 9 cin>>n>>m; 10 for(int i=1; i<=m; i++){ 11 memset(is, false, sizeof(is)); 12 cin>>s[0]; 13 for(int j=1; j<=s[0]; j++){ 14 cin>>s[j]; 15 is[s[j]]=true; 16 } 17 for(int j=s[1]; j<=s[s[0]]; j++){ 18 if(!is[j]){ 19 for(int k=1; k<=s[0]; k++){ 20 if(!edge[j][s[k]]){ 21 edge[j][s[k]]=true; 22 degree[s[k]]++; 23 } 24 } 25 } 26 } 27 } 28 do{ 29 top=0; 30 for(int i=1; i<=n; i++){ 31 if(!degree[i] && !vis[i]){ 32 topo[++top]=i; 33 vis[i]=true; 34 } 35 } 36 for(int i=1; i<=top; i++){ 37 for(int j=1; j<=n; j++){ 38 if(edge[topo[i]][j]){ 39 edge[topo[i]][j]=false; 40 degree[j]--; 41 } 42 } 43 } 44 ans++; 45 }while(top); 46 --ans; 47 cout<<ans<<endl; 48 return 0; 49 }