1002 [NOIP2013]车站分级 拓扑排序 超级站点 给不好直接连边的点连边 给有层级关系但是没法直接标明的序列划分等级
链接:https://ac.nowcoder.com/acm/contest/26077/1002
来源:牛客网
题目描述
车站编号 |
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 个火车站至少分为几个不同的级别。
输入描述:
输出描述:
输出只有一行,包含一个正整数,即n个火车站最少划分的级别数。
输入
复制9 2 4 1 3 5 6 3 3 5 6
输出
复制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; } /*样例区 */ //------------------------------------------------------------