车站分级 题解

车站分级1

题目信息

见链接

解题思路

这道题可以用拓扑排序2

把题意简化一下,就是:

如果你停靠了一个站点,所有等级大于等于这个站点的站点都要停靠,反过来也就是所有起始站和终点站中间没有停靠的站点的等级一定是小于停靠的站点。

所以我们把起点终点所有没停靠的站点和所有停靠的站点连成边,然后拓扑排序,输出最后一个(入度最大的)顶点的入度(即题目所要求的分级)。
C ⁡ + + \operatorname C++ C++ 代码如下 3

#include 
using namespace std;
struct rec {
    int number, level;
};
int n, m, a[10010], graph[3010][3010], inDegree[10010], head[4000010], ver[4000010], Next[4000010], tot, ans = 1, s; //inDegree[]存顶点的入度,head[]、next[]、ver[]存图
//用数组模拟链表
bool v[10010];
queue<rec> q;
void add(int x, int y) {
    tot++;
    ver[tot] = y;
    Next[tot] = head[x];
    head[x] = tot;
}
int main() {
    cin >> n >> m;
    memset(graph, false, sizeof(graph));
    for (int i = 1; i <= m; i++) {
        memset(v, false, sizeof(v));
        cin >> s;
        for (int j = 1; j <= s; j++) {
            cin >> a[j];
            v[a[j]] = true;
        }
        for (int j = a[1]; j <= a[s]; j++) {
            if (v[j])
                continue;
            for (int k = 1; k <= s; k++) {
                if (graph[a[k]][j])
                    continue;
                inDegree[j]++;
                graph[a[k]][j] = true;
                add(a[k], j);
            }
        }
    }
    for (int i = 1; i <= n; i++)
        if (inDegree[i] == 0) {
            rec now;
            now.number = i;
            now.level = 1;
            q.push(now);
        }
    while (q.size())
    {
        rec now = q.front();
        q.pop();
        int x = now.number, z = now.level;
        for (int i = head[x]; i; i = Next[i])
        {
            int y = ver[i];
            inDegree[y]--;
            if (inDegree[y] == 0)
            {
                rec NexT;
                NexT.number = y, NexT.level = z + 1;
                q.push(NexT);
                ans = max(ans, NexT.level);
            }
        }
    }
    cout << ans << endl;
    return 0;
}

  1. 2013年NOIP普及组第4题 ↩︎

  2. 拓扑排序:百度百科 ↩︎

  3. 如果用邻接矩阵存图,数组要开的很大,可能会MLE,所以我就用邻接链表储存。 ↩︎

你可能感兴趣的:(OI)