超水
题目在上面,这个是一个经典的拓扑排序和建图的模板,大家可以试试水,首先我们要理解题目,假设有一串编号1 3 5,这个就是1,5分别是起点和终点,而且只停靠3,所以2,4这两个车站必须要小于,1、3、5这三个,而其中三个关系是:1≤3≤5,本着贪心的原则:能等则等所以我们令他们相等,那么我们可以这样建图,如果2<3的话(注意没有等于),那么我们就添加一条从2通向3的边,这样我们只需要计算生成的这个图最大有几层就好了,原因是:如果2->3->5的话意味着2<3<5,所以要三级才可以,这一块是重点,没有理解的可以留言。
那么我们只需要计算图最大有几层就好了,我们可以用拓扑排序,然后DP计算,我们定义d[i]表示到i点的最大层数是多少,知道拓扑排序的都知道这个按着拓扑排序DP就好了。
下面上代码:
#include<iostream>
#include<cstring>
#include<queue>
#include<cstdio>
using namespace std;
queue <int> q;//拓扑排序用的数组
int map[1010][1010],num[1010],d[1010],n,v[1010],stan[1010];
int read()
{
char ch;
while(ch=getchar(),ch<'0' || ch>'9');
int num=ch-'0';
while(ch=getchar(),ch>='0' && ch<='9')
num=num*10+ch-'0';
return num;
}
void write(int n){
if(n==0) return;
write(n/10);
putchar(n%10+'0');
}
int main()
{
int m,ans=0,x;
n=read();
m=read();
for(int i=1;i<=m;i++)//读入数据
{
int x,s0=0,s1;
x=read();
memset(v,0,sizeof(v));
for(int j=1;j<=x;j++)
{
stan[j]=read();//快读一下
v[stan[j]]=1;
}
for(int j=stan[1]+1;j<stan[x];j++)
{
if(v[j]==1)
continue;
for(int k=1;k<=x;k++)
{
map[j][stan[k]]=1;//寻找没有停靠的点,在枚举所有有停靠的点见一条从前者到后者的边
}
}
}
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
if(map[i][j]==1)
num[j]++;//拓扑排序统计一下每个点的入度
}
for(int i=1;i<=n;i++)//入度为0的入队计算
{
if(num[i]!=0)
continue;
d[i]=1;
q.push(i);
}
while(!q.empty())//循环拓扑排序
{
x=q.front();//取队头
q.pop();
for(int i=1;i<=n;i++)//枚举所有与它相邻的点
{
if(map[x][i]==1)//相邻
{
num[i]--;//去边
d[i]=max(d[x]+1,d[i]);//DP
if(d[i]>ans)//找答案
ans=d[i];
if(num[i]==0)
q.push(i);
}
}
}
write(ans);//快输一波
return 0;
}
希望大家可以AC,有不懂得可以留言,有错误也欢迎指出。