[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;
}

 

posted @ 2017-10-17 18:45  Mrsrz  阅读(398)  评论(0编辑  收藏  举报