P1983-车站分级【图论,记忆化dfs,构图】

正题

题目链接:https://www.luogu.org/problemnew/show/P1983


题目大意

一个辆车会一个一个值xxx,如果等级大于等于xxx的车站都会停靠(包括起点和终点)。给每辆车的停靠点,求至少要将车站分多少级。


解题思路

对于一辆车,若一个点他经过了却没有停靠,那么这个点比所有的停靠点的等级都要低。然后根据这个关系连边,然后记忆化dfsdfsdfs。时间复杂度O(nm2)O(nm^2)O(nm2),边比较多,建议用邻接矩阵。但是是14\frac{1}{4}41​常数,所以可以过。

可以优化成O(nm)O(nm)O(nm)的。对于没辆车,我们的边数是O(nm)O(nm)O(nm)条的密集图,所以我们可以建立一个虚点,然后将边数变为O(n+m)O(n+m)O(n+m)条。


codecodecode

#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
const int N=1050;
int ans,n,m,a[2*N][2*N],f[N];
bool v[N];
int dfs(int x){
    if(f[x]) return f[x];
    for (int i=1;i<=n+m;i++) 
      if(a[x][i]) f[x]=max(f[x],dfs(i));
    if(x>n) f[x]--;
    return ++f[x];
}
int main()
{
	scanf("%d%d",&n,&m);
	for(int i=1;i<=m;i++){
		int t,x,star,end;
		memset(v,0,sizeof(v));
		scanf("%d",&t);
		for(int j=1;j<=t;j++){
			scanf("%d",&x);
			a[x][n+i]=1;v[x]=1;
			if(j==1) star=x;
			if(j==t) end=x;
		}
		for(int j=star;j<=end;j++){
			if(v[j]) continue;
			a[n+i][j]=1;
		}
	}
	for(int i=1;i<=n;i++)
	  ans=max(ans,dfs(i));
	printf("%d",ans);
}
上一篇:NOIP-2021


下一篇:leetcode(84)柱状图中最大的矩形