• 洛谷 P1983: 车站分级(拓扑排序)


    https://www.luogu.org/problemnew/show/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)中,首先是一个正整数 si(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。

    解题思路:

    如果这趟车次停靠了火车站 x,则始发站、终点站之间所有级别大于等于火车站x 的都必须停靠

    说明所有没有停靠的站都小于任何一个停靠的站,所以把这些站之间两两建边,拓扑排序看最多有几层,

    需要注意的是建边时时间可能会超限,注意重边和预处理停靠的站和未停靠的站。

    #include <stdio.h>
    #include <queue>
    #include <vector>
    #include <algorithm>
    #define N 1020
    using namespace std;
    
    int n, m;
    int indegree[N], a[N], b[N], books[N][N];
    vector<int>e[N];
    struct edge {
    	int start;
    	int temp;
    };
    queue<edge>q;
    int bfs()
    {
    	int i, v, s, ans = 1;
    	
    	for(i=1; i<=n; i++)
    		if (indegree[i] == 0)
    			q.push(edge{ i, 1 });
    	while (!q.empty())
    	{
    		edge u = q.front();
    		q.pop();
    		s = u.start;
    		ans = max(ans, u.temp);
    		for (i = 0; i < e[s].size(); i++)
    		{
    			v = e[s][i];
    			indegree[v]--;
    			if (indegree[v] == 0)
    				q.push(edge{ v, u.temp + 1 });
    		}
    	}
    	return ans;
    }
    int main()
    {
    	int i, j, k, l, len;
    	scanf("%d%d", &n, &m);
    	while (m--)
    	{
    		scanf("%d", &k);
    		for (i = 0; i < k; i++)
    			scanf("%d", &a[i]);
    		l = 1;
    		len = 0;
    		for (j = a[0] + 1; j < a[k - 1]; j++)
    		{
    			if (j == a[l])
    			{
    				l++;
    				continue;
    			}
    			b[len++] = j;
    		}
    		for (i = 0; i < k; i++)
    		{
    			for (j = 0; j < len; j++)
    			{
    				if (books[a[i]][b[j]])
    					continue;
    				e[a[i]].push_back(b[j]);
    				indegree[b[j]]++;
    				books[a[i]][b[j]] = 1;
    			}
    			
    		}
    	}
    	printf("%d
    ", bfs());
    	return 0;
    }
  • 相关阅读:
    筛选法求素数
    C/C++经典面试题目
    操作系统笔试面试基本内容
    Win32/MFC的基本概念
    STL采用的标准模板库
    数据结构基本概念
    SQL基础语句
    C/C++基础概念
    计算机网络基础概念
    流水作业 批作业调度
  • 原文地址:https://www.cnblogs.com/zyq1758043090/p/11852564.html
Copyright © 2020-2023  润新知