1002 [NOIP2013]车站分级 拓扑排序 超级站点 给不好直接连边的点连边 给有层级关系但是没法直接标明的序列划分等级
作者:互联网
链接: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