8
20
2015
0

[题解][NOIP2013普及]车站分级

关键字:最长路。

Link&Limit


[洛谷1983]  [codevs3294]

时间限制:1000ms  空间限制:131072kb

Description


一条单向的铁路线上,依次有编号为 1, 2, …, n 的 n 个火车站。每个火车站都有一个级别,最低为 1 级。现有若干趟车次在这条线路上行驶,每一趟都满足如下要求:如果这趟车次停靠了火车站 x,则始发站、终点站之间所有级别大于等于火车站 x 的都必须停靠。(注意:起始站和终点站自然也算作事先已知需要停靠的站点)

例如,下表是 5 趟车次的运行情况。其中,前 4 趟车次均满足要求,而第 5 趟车次由于停靠了 3 号火车站(2 级)却未停靠途经的 6 号火车站(亦为 2 级)而不满足要求。

[题解][NOIP2013普及]车站分级 - TsReaper - TsReaper的博客

现有 m 趟车次的运行情况(全部满足要求),试推算这 n 个火车站至少分为几个不同的级别。

Input Format


第一行包含 2 个正整数 n, m,用一个空格隔开。

第 i + 1 行(1 ≤ i ≤ m)中,首先是一个正整数 si(2 ≤ si ≤ n),表示第 i 趟车次有 si 个停靠站;接下来有 si个正整数,表示所有停靠站的编号,从小到大排列。每两个数之间用一个空格隔开。输入保证所有的车次都满足要求。

Output Format


输出只有一行,包含一个正整数,即 n 个火车站最少划分的级别数。

Sample Input #1


9 2

4 1 3 5 6

3 3 5 6

Sample Output #1


2

Sample Input #2


9 3

4 1 3 5 6

3 3 5 6

3 1 5 9

Sample Output #2


3

Hint


对于 20%的数据,1 ≤ n, m ≤ 10;

对于 50%的数据,1 ≤ n, m ≤ 100;

对于 100%的数据,1 ≤ n, m ≤ 1000。

本题主要是抓住各个车站间的关系。显然,若列车的停靠站为a1,a2,...,an,那么a1~an之间没有停靠的站点等级一定比a1~an来得低。所以,我们将低等级站点向高等级站点连边,跑一边最长路就知道最高等级的站点是多少了。

#include <stdio.h>
#define QLEN 1005
int n,m,ans = 0,l[1010];
int e[1001010][2],p[1010],tot = 0;
int q[1010],dis[1010],head,tail;
short vis[1010],flag[1010],hase[1010][1010];
int max(int a,int b)
{
    return a>b?a:b;
}
void adde(int sn,int fn)
{
    e[++tot][0] = fn; e[tot][1] = p[sn]; p[sn] = tot;
}
void bfs()
{
    int i,sn,fn;
    head = 1; tail = 2;
    vis[0] = 1; 
    while(head != tail)
    {
        sn = q[head++];
        for(i=p[sn];i;i=e[i][1])
        {
            fn = e[i][0];
            if(dis[fn]>=dis[sn]+1) continue;
            dis[fn] = dis[sn]+1; ans= max(ans,dis[fn]);
            if(vis[fn]) continue;
            vis[fn] = 1; q[tail++] = fn;
            if(tail>QLEN) tail = 1;
        }
        vis[sn] = 0;
        if(head>QLEN) head = 1;
    }
}
int main()
{
    int i,j,cnt;
    scanf("%d%d",&n,&m);
    while(m--)
    {
        scanf("%d",&cnt);
        for(i=1;i<=cnt;i++) { scanf("%d",&l[i]); flag[l[i]] = 1;}
        for(i=l[1];i<=l[cnt];i++)
        {
            if(flag[i]) continue;
            for(j=1;j<=cnt;j++) if(!hase[i][l[j]]) { adde(i,l[j]); hase[i][l[j]] = 1;}
        }
        for(i=1;i<=cnt;i++) flag[l[i]] = 0;
    }
    for(i=1;i<=n;i++) adde(0,i);
    bfs();
    printf("%d",ans);
    return 0;
}
Category: 题解 | Tags: 图论 洛谷 codevs | Read Count: 302

登录 *


loading captcha image...
(输入验证码)
or Ctrl+Enter

| Theme: Aeros 2.0 by TheBuckmaker.com