[NOIP2013普及组]车站分级
题目:洛谷P1983、Vijos P1851、codevs3294。
题目大意:有一些车停靠某些站。现在要给所有站分级,规定一辆车停靠的所有站的最小级数必须大于(起点-终点)所有不停靠的站的最大级数。问至少分成几种不同的级数?
解题思路:由于停靠的站级数大于不停靠的站,我们把每列车停靠的站向不停靠的连一条有向边。
然后对其进行拓扑排序,拓扑序列的最大值就是答案。
注意在连边时先枚举不停靠的站,因为如果它停靠了就可以直接跳过循环,避免不必要的操作(反过来就TLE了)。
C++ Code:
#include<cstdio> #include<cstring> #include<cctype> bool b[1011][1011],use[1011]; int n,m,d[1011],a[1011],ceng[1011],q[123457]; inline int readint(){ char c=getchar(); for(;!isdigit(c);c=getchar()); int p=0; for(;isdigit(c);c=getchar())p=(p<<3)+(p<<1)+(c^'0'); return p; } int main(){ memset(d,0,sizeof d); memset(b,0,sizeof b); m=readint(); n=readint(); for(int i=1;i<=n;++i){ memset(use,0,sizeof use); int num=readint(); for(int j=1;j<=num;++j) use[a[j]=readint()]=true; for(int k=a[1];k<=a[num];++k) if(!use[k]){ for(int j=1;j<=num;++j) if(!b[a[j]][k]){ b[a[j]][k]=true; ++d[k]; } } } int l=0,r=0,ans=1; memset(ceng,0,sizeof ceng); for(int i=1;i<=m;++i) if(!d[i])ceng[q[++r]=i]=1; while(l!=r){ int u=q[++l]; for(int i=1;i<=m;++i) if(b[u][i]&&!--d[i]){ ans=ceng[q[++r]=i]=ceng[u]+1; } } printf("%d\n",ans); return 0; }