[NOIP2013 普及组] 车站分级

#include <cstdio>
#include <cstring>
#include <iostream>
 
using namespace std;
 
const int N = 2010, M = 1000 * 1000 + 10;
 
int n, m;
int d[N];//记录一个点的入度
bool st[N];//标记该点是否为停靠点
int dist[N];//dist[i]表示i这个点级别最低是多少
int q[N], hh, tt = -1;//拓扑排序数组
int h[N], e[M], ne[M], w[M],idx;//邻接表数组
 
void add(int a, int b, int c)//邻接表模板
{
    d[b] ++ ;//b入度加1
    e[idx] = b;
    w[idx] = c;
    ne[idx] = h[a];
    h[a] = idx;
    idx ++ ;
}
 
void topsort()//拓扑排序模板
{
    for (int i = 1; i <= n + m; i ++ )//要算上一个虚拟点
        if (!d[i]) q[++ tt] = i;
    
    while (hh <= tt)
    {
        int t = q[hh ++ ];
        for (int i = h[t]; i != -1; i = ne[i])
        {
            int j = e[i];
            if (-- d[j] == 0) q[++ tt] = j;
        }
    }
}
 
int main()
{
    cin >> n >> m;
    memset(h, -1, sizeof h);
    for (int i = 1; i <= m; i ++ )
    {
        int cnt;
        scanf("%d", &cnt);
        memset(st, 0, sizeof st);
        int start = n, last = 1;//表示该车次从哪个车站开始到哪个车站结束
        
        while (cnt -- )
        {
            int stop;
            scanf("%d", &stop);
            st[stop] = true;//表示stop为停靠点
            start = min(start, stop);
            last = max(last, stop);
        }
        
        int ver = n + i;//在非停靠边和停靠边之间建立一个虚拟点
        for (int j = start; j <= last; j ++ )//从start开始到last结束
            if (st[j]) add(ver, j, 1);
            else add(j, ver, 0);
    }
    
    topsort();
    
    for (int i = 1; i <= n; i ++ ) dist[i] = 1;//每个车站级别最低为1,这里也可以建立一个虚拟源点,虚拟源点到每个点的权值为1
    for (int i = 0; i < n + m; i ++ )//加上虚拟源点
    {
        int j = q[i];
        for (int k = h[j]; k != -1; k = ne[k])
            dist[e[k]] = max(dist[e[k]], dist[j] + w[k]);//求最小的级别要用最长路,这里和差分约束的思想一样
    }
    
    int res = 0;
    for (int i = 1; i <= n; i ++ ) res = max(res, dist[i]);//找出所有符合条件的级别中最大的那个
    
    cout << res << endl;
    
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
noip2013普及组初赛是全国信息学奥林匹克联赛的一场选拔赛。该比赛旨在选拔初学者,对编程和算法有一定基础的学生,通过比赛形式来考察他们的知识水平和解题能力。 比赛题目通常会涉及各个领域的算法和数据结构,如图论、动态规划、数论等。题目难度逐步增加,从简单的输出结果,到复杂的程序设计与代码实现,考察选手的逻辑思维和编程能力。 参赛选手需要通过自己的思考和编程实现来解决题目,同时时间也是一个重要因素。比赛中,选手需要在规定的时间内独立完成所有题目,对于复杂的题目需要迅速想出解题思路并进行编码。因此,在比赛中,选手的临场发挥和解题速度也是需要考虑的因素。 noip2013普及组初赛的结果将作为选拔阶段的一个重要依据,选出表现出色的选手进入到更高阶段的比赛,对于他们来说,这是一次展示自己实力的机会。 此外,noip2013普及组初赛,也给了参赛选手一个交流的平台。选手们可以通过比赛结交同好,相互切磋,共同进步。同时,比赛结束后,还有详细的解题分析和讲解,有助于参赛选手对自己在比赛中的不足进行反思与改进。 总之,noip2013普及组初赛是一个考察学生编程和算法能力的选拔赛,通过比赛的形式来选拔出优秀的选手。这对于参赛选手来说,是一次展示自己才华的机会,也是一个展示自己实力和提高自己能力的平台。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值