【SSL】2264 &【洛谷】P1983车站分级

【SSL】2264 &【洛谷】P1983车站分级

题目描述

一条单向的铁路线上,依次有编号为 1, 2, …, n的 n个火车站。每个火车站都有一个级别,最低为 1 级。现有若干趟车次在这条线路上行驶,每一趟都满足如下要求:如果这趟车次停靠了火车站 x,则始发站、终点站之间所有级别大于等于火车站x 的都必须停靠。(注意:起始站和终点站自然也算作事先已知需要停靠的站点)

例如,下表是5趟车次的运行情况。其中,前4 趟车次均满足要求,而第 5 趟车次由于停靠了 3 号火车站(2 级)却未停靠途经的 6 号火车站(亦为 2 级)而不满足要求。

现有 m 趟车次的运行情况(全部满足要求),试推算这n 个火车站至少分为几个不同的级别。

输入格式

第一行包含 2 个正整数 n,m,用一个空格隔开。

第 i +1行(1≤i≤m)中,首先是一个正整数 (2≤si ≤n),表示第i 趟车次有 si个停靠站;接下来有si个正整数,表示所有停靠站的编号,从小到大排列。每两个数之间用一个空格隔开。输入保证所有的车次都满足要求。

输出格式

一个正整数,即 n 个火车站最少划分的级别数。

输入输出样例

输入 #1
9 2 
4 1 3 5 6 
3 3 5 6 
输出 #1
2
输入 #2
9 3 
4 1 3 5 6 
3 3 5 6 
3 1 5 9 
输出 #2
3

说明/提示

对于20%的数据,1 ≤ n, m ≤ 10;

对于 50%的数据,1 ≤ n, m ≤ 100;

对于100%的数据,1 ≤ n, m ≤ 1000。

思路

在路径上的点级别大于不在路径上的点级别。
建边。
判重边。
减小重边占用的空间。

代码

slow

#include<iostream>
#include<cstdio>
#include<queue>
#include<cstring>
using namespace std;
int ans[1010],tot=0,n,m,head[1010],ins[1010],a[1010];
bool b[1010][1010]; 
struct jgt
{
    
    
	int x,y,nxt;
}f[1000010];
queue<int> q;
void input()
{
    
    
	int i,j,k,l,t;
	memset(head,0,sizeof(head));
	memset(ins,0,sizeof(ins));
	memset(ans,0,sizeof(ans));
	memset(b,0,sizeof(b));
	scanf("%d%d",&n,&m);
	for(i=1;i<=m;i++)
	{
    
    
		memset(a,0,sizeof(a));
		scanf("%d",&t);
		for(j=1;j<=t;j++)
			scanf("%d",&a[j]);
		for(j=1;j<=t;j++)
		{
    
    
			for(k=a[1]+1,l=2;k<a[t];k++)
			{
    
    
				if(k==a[l])
					l++;
				else
				{
    
    
					if(!b[k][a[j]])//判重边 
					{
    
    
						tot++;
						f[tot].x=k;
						f[tot].y=a[j];
						f[tot].nxt=head[k];
						head[k]=tot;
						ins[a[j]]++;
						b[k][a[j]]=1;
					}
				}
			}
		}
	}
	return;
}
void topsort()
{
    
    
	int i,answer=0;
	for(i=1;i<=n;i++)
		if(!ins[i])
		{
    
    
			q.push(i);
			ans[i]=1;
		}
	for(;!q.empty();q.pop())
	{
    
    
		for(i=head[q.front()];i;i=f[i].nxt)//更新入度 
		{
    
    
			ins[f[i].y]--;
			ans[f[i].y]=max(ans[f[i].y],ans[q.front()]+1);
			if(!ins[f[i].y])//当能够到达这个点的所有点都遍历过后将这个点加入队列
				q.push(f[i].y);
		}
	}
	for(i=1;i<=n;i++)
		answer=max(answer,ans[i]);
	printf("%d",answer);
	return;
}
int main()
{
    
    
	input();
	topsort();
	return 0;
}

fast

#include<iostream>
#include<cstdio>
#include<queue>
#include<cstring>
using namespace std;
int ans[1010],tot=0,n,m,head[1010],ins[1010],a[1010];
int i,j,k,l,t,answer,tem;
bool b[1010][1010]; 
int x[1000010],y[1000010],nxt[1000010];
queue<int> q;
int read()//快读
{
    
    
	int ans=0;
	char c;
	for(c=getchar();c<'0'||c>'9';c=getchar());
	for(ans=c-48,c=getchar();'0'<=c&&c<='9';c=getchar())ans=(ans<<3)+(ans<<1)+c-48;
	return ans;
}
int main()
{
    
    
	n=read(),m=read();
	for(i=1;i<=m;i++)
	{
    
    
		t=read();
		for(j=1;j<=t;j++)
			a[j]=read();
		k=a[1]+1;
		for(j=2;j<=t;j++,k++)
			for(;k<a[j];k++)
				for(l=1;l<=t;l++)
					if(!b[k][a[l]])//判重边 
					{
    
    
						tot++;
						x[tot]=k;
						y[tot]=a[l];
						nxt[tot]=head[k];
						head[k]=tot;
						ins[a[l]]++;
						b[k][a[l]]=1;
					}
	}
	for(i=1;i<=n;i++)
		if(!ins[i])
		{
    
    
			q.push(i);
			ans[i]=1;
		}
	for(;!q.empty();q.pop())
		for(tem=q.front(),i=head[tem];i;i=nxt[i])//更新入度 
		{
    
    
			ins[y[i]]--;
			ans[y[i]]=max(ans[y[i]],ans[tem]+1);
			if(!ins[y[i]])//当能够到达这个点的所有点都遍历过后将这个点加入队列
				q.push(y[i]);
		}
	for(i=1;i<=n;i++)
		answer=max(answer,ans[i]);
	printf("%d",answer);
	return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_46975572/article/details/112911619