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

正题

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


题目大意

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


解题思路

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

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


c o d e code code

#include
#include
#include
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);
}

你可能感兴趣的:(dp,深搜,图论)