ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

1002 [NOIP2013]车站分级 拓扑排序 超级站点 给不好直接连边的点连边 给有层级关系但是没法直接标明的序列划分等级

2022-08-17 18:34:05  阅读:124  来源: 互联网

标签:连边 NOIP2013 idx int 火车站 车次 站台 级别 1002


链接:https://ac.nowcoder.com/acm/contest/26077/1002
来源:牛客网

题目描述

一条单向的铁路线上,依次有编号为1, 2, …, n 的n 个火车站。每个火车站都有一个级别,最低为1 级。现有若干趟车次在这条线路上行驶,每一趟都满足如下要求:如果这趟车次停靠了火车站x,则始发站、终点站之间所有级别大于等于火车站x 的都必须停靠。(注意:起始站和终点站自然也算作事先已知需要停靠的站点) 例如,下表是5 趟车次的运行情况。其中,前4 趟车次均满足要求,而第5 趟车次由于停靠了3 号火车站(2 级)却未停靠途经的6 号火车站(亦为2 级)而不满足要求。


车站编号

1

 

2

 

3

 

4

 

5

 

6

 

7

 

8

 

9

车站级别

车次

3

 

1

 

2

 

1

 

3

 

2

 

1

 

1

 

3

1

 

 

 

 

 

 

2

 

 

 

 

 

 

 

 

 

 

3

4

 

 

 

 

 

 

5

 

 

 

 

 

现有 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

输出

复制
2
示例2

输入

复制
9 3
4 1 3 5 6
3 3 5 6
3 1 5 9

输出

复制
3

备注:

对于20%的数据,1 ≤n,m ≤10;
对于50%的数据,1 ≤n,m≤100;
对于100%的数据,1 ≤n,m ≤ 1000。

 

分析

N大小设错了,麻了,好多发搞了好久

题意大概是:当前车次行程中的所有站台的级别都比非站台的级别高。问这些站台总共有多少个级别

可以将所有非站台向站台连接一条长度为1的边,按照拓扑序给每个点标记距离更新距离

1 1 0 0 1 1 这样中间两个0就是1级,旁边的1就是二级

再加一段:1 1 1 0 1 1 这样这个0就是1级,原本是0变成1的位置就是2级,旁边的1变成了3级

内在的拓扑序是:0的所有边更新完了,然后1被放入队列,1的所有边被更新完了,旁边的1被放入队列

无法贪心的原因:因为有些车次可能长度不长:1 0 0 1 1 0。这样没办法通过0的数量或者1的数量来判断右边那个0到底是哪一级的(大概?)

反正拓扑序写的话绝对正确。

另外1e3的范围确实可以直接暴力写。

但是假如是1e5的范围,这样就不行了。这时候考虑

设一个特殊点:ver。表示车次

将所有当前车次所有站台都向非站台,可以将所有非站台连向车次,边长为1,再车次连向站台,边长为0。最后拓扑序就可以解决。

//-------------------------代码----------------------------

//#define int ll
const int N = 1000005,M = 2e3+10;
int n,m,d[M],e[N],ne[N],w[N],h[2010],idx;

void add(int a,int b,int c) {
    e[idx] = b,ne[idx] = h[a],w[idx] = c,d[b] ++ ,h[a] = idx ++ ;
}
bool vis[2010];
int ans[M],sum,dist[M];
void bfs() {
    queue<int> q;
    fo(i,1,n+m) {
        if(!d[i]) q.push(i);
    }
    while(q.size()) {
        int node = q.front();q.pop();ans[++sum] = node;
        fe(i,node) {
            int v = e[i];
            if(--d[v] == 0) q.push(v);
        }
    }
}

void solve()
{
    cin>>n>>m;
    ms(h,-1);ms(vis,0);
    fo(i,1,m) {
        ms(vis,0);
        int cnt;cin>>cnt;
        int start = n,end = 1;
        while(cnt -- ) {
            int stop;
            cin>>stop;
            start = min(start,stop);
            end = max(end,stop);
            vis[stop] = 1;
        }
        int ver = n + i;
        for(int j = start;j<=end;j++) {
            if(!vis[j]) add(j,ver,0);//非停靠点连接虚拟点
            else add(ver,j,1);//虚拟点连接停靠点
        }
    }
    bfs();
//     db(sum);
    for(int i = 1;i<=n;i++) dist[i] = 1;
    fo(i,1,sum) {
        int u = ans[i];
        for(int j = h[u];~j;j=ne[j]) {
            int v = e[j];
            int W = w[j];
            dist[v] = max(dist[v],dist[u] + W);
        }
    }
    int res = 0;
    fo(i,1,n) res = max(res,dist[i]);
    cout<<res<<endl;
}
void main_init() {}
signed main(){
    AC();clapping();TLE;
    cout<<fixed<<setprecision(12);
    main_init();
//  while(cin>>n,n)
//  while(cin>>n>>m,n,m)
//    int t;cin>>t;while(t -- )
    solve();
//    {solve(); }
    return 0;
}

/*样例区


*/

//------------------------------------------------------------

 

标签:连边,NOIP2013,idx,int,火车站,车次,站台,级别,1002
来源: https://www.cnblogs.com/er007/p/16596302.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有