1 solutions

  • 0
    @ 2024-6-12 10:06:16

    模拟($Oknm$90pts)

    • 遍历每轮车次,找到停留的车站区间里面, 没有停留的车的层级的最大值,和停留的车站的最小值,如果最小值小于等于最大值,就尝试去更新每个停留的车站的最小值。
    #include<bits/stdc++.h>
    using namespace std;
    const int N=1010;
    int s[N],a[N][N];
    bool st[N][N];
    int res[N];
    int main()
    {
    	int n,m;
    	cin>>n>>m;   
    	for(int i=1;i<=m;i++)
    	{
    		cin>>s[i];
    		for(int j=1;j<=s[i];j++) //获取每个车次的车站
    		{
    			cin>>a[i][j];
    			st[i][a[i][j]]=1;
    		}
    	}
    	for(int i=1;i<=n;i++) //初始化
    	{
    		res[i]=1;
    	}
    	while(true)
    	{
    		int cnt=0;
    		for(int i=1;i<=m;i++)
    		{	
    			int maxv=0; //没有停留的车站的最大值
    			int minv=min(res[a[i][1]],res[a[i][s[i]]]); //停留的最小值
    			for(int j=a[i][1]+1;j<=a[i][s[i]]-1;j++) //枚举区间内的所有车站
    			{
    				if(!st[i][j]) //没有停过
    				{
    					maxv=max(maxv,res[j]); //更新最大值
    				}
    				else
    				{
    					minv=min(minv,res[j]); //更新最小值
    				}
    			}
    			if(minv<=maxv) //不满足停留站都大于等于非停留站
    			{
    				for(int j=a[i][1];j<=a[i][s[i]];j++) //枚举每个站点
    				{
    					if(st[i][j]) //停留过,更新最大值
    					{	
    					    res[j]=max(res[j],maxv+1);
    					}
    				}
    				cnt++; //至少有一个车次不满足要求
    			}
    		}
    		if(cnt==0) //m轮车次都执行过了,没有需要更新的操作
    		{
    			break;
    		}
    	}
    	int maxv=0;
    	for(int i=1;i<=n;i++) //找到车站等级最大的点
    	{
    		maxv=max(maxv,res[i]);
    	}
    	cout<<maxv;
        return 0;
    }
    

    拓扑排序(O(n+m)O(n+m))

    • 如果我们对于每轮车次进行建图,那么边的数目为n22\frac {n^2} 2,一共有mm轮,那么边的总数就大概为mn22\frac {mn^2} 2,这样就会超内存,如果我们建立个虚拟点,使得没有停留过的点到虚拟点的边权是0,虚拟点到停留过的点的边权是1.
    #include<bits/stdc++.h>
    using namespace std;
    const int N=2010,M=1000010;
    int q[N];
    int h[N],e[M],ne[M],w[M],idx;
    int n,m;
    bool st[N];
    int dist[N],d[N];
    void add(int a,int b,int c) //添加一条a到b的边,权值为c
    {
        e[idx]=b,ne[idx]=h[a],w[idx]=c,h[a]=idx++;
        d[b]++; //入度增加
    }
    void topsort() //拓扑排序
    {
        int hh=0,tt=-1;
        for(int i=1;i<=n+m;i++)
        {
            if(d[i]==0)
            {
                q[++tt]=i;
            }
        }
        while(hh<=tt)
        {
            int t=q[hh++];
            for(int i=h[t];i!=-1;i=ne[i])
            {
                int j=e[i];
                d[j]--;
                if(d[j]==0) //j这个点已经没有点可以入边了
                {
                    q[++tt]=j;
                }
            }
        }
    }
    int main()
    {
        cin>>n>>m; 
        memset(h,-1,sizeof h); //初始化邻接表
        for(int i=1;i<=m;i++)
        {
            int cnt;
            cin>>cnt;
            int l=n,r=0;
            memset(st,0,sizeof st); //初始化站台状态
            for(int j=1;j<=cnt;j++) //找到当前车次停留的状态
            {
                int x;
                cin>>x;
                l=min(l,x);
                r=max(r,x);
                st[x]=1;
            }
            int ver=n+i; //添加一个中转站
            for(int j=l;j<=r;j++)
            {
                if(st[j]) add(ver,j,1); //停留过的点
                else add(j,ver,0); //没有停留过的点
            }
        }
        topsort(); //拓扑排序
        for(int i=1;i<=n;i++) //初始化距离
        {
            dist[i]=1;
        }
        for(int i=0;i<n+m;i++) //枚举每个站次
        {
            int t=q[i];
            for(int k=h[t];k!=-1;k=ne[k])
            {
                int j=e[k];
                dist[j]=max(dist[j],dist[t]+w[k]);
            }
        }
        int res=0;
        for(int i=1;i<=n;i++) //找到所有站的最大值
        {
            res=max(res,dist[i]);
        }
        cout<<res;
        return 0;
    }
    
    • 1

    Information

    ID
    444
    Time
    500ms
    Memory
    128MiB
    Difficulty
    10
    Tags
    # Submissions
    5
    Accepted
    2
    Uploaded By