1. 程式人生 > 其它 >[luogu p1983] 車站分級

[luogu p1983] 車站分級

技術標籤:java演算法資料結構dfs

傳送門

車站分級

題目描述

一條單向的鐵路線上,依次有編號為 \(1, 2, ..., n\)\(n\)個火車站。每個火車站都有一個級別,最低為 \(1\) 級。現有若干趟車次在這條線路上行駛,每一趟都滿足如下要求:如果這趟車次停靠了火車站 \(x\),則始發站、終點站之間所有級別大於等於火車站\(x\) 的都必須停靠。(注意:起始站和終點站自然也算作事先已知需要停靠的站點)

例如,下表是\(5\)趟車次的執行情況。其中,前\(4\) 趟車次均滿足要求,而第 \(5\) 趟車次由於停靠了 \(3\) 號火車站(\(2\) 級)卻未停靠途經的 \(6\)

號火車站(亦為 \(2\) 級)而不滿足要求。

現有 \(m\) 趟車次的執行情況(全部滿足要求),試推算這$ n$ 個火車站至少分為幾個不同的級別。

輸入輸出格式

輸入格式

第一行包含 \(2\) 個正整數 \(n, m\),用一個空格隔開。

\(i + 1\)\((1 ≤ i ≤ m)\)中,首先是一個正整數 \(s_i(2 ≤ s_i ≤ n)\),表示第$ i$ 趟車次有 \(s_i\) 個停靠站;接下來有$ s_i$個正整數,表示所有停靠站的編號,從小到大排列。每兩個數之間用一個空格隔開。輸入保證所有的車次都滿足要求。

輸出格式

一個正整數,即 \(n\) 個火車站最少劃分的級別數。

輸入輸出樣例

輸入樣例 #1

9 2
4 1 3 5 6
3 3 5 6

輸出樣例 #1

2

輸入樣例 #2

9 3
4 1 3 5 6
3 3 5 6
3 1 5 9

輸出樣例 #2

3

說明

對於\(20\%\)的資料,\(1 ≤ n, m ≤ 10\)

對於 \(50\%\)的資料,\(1 ≤ n, m ≤ 100\)

對於 \(100\%\)的資料,\(1 ≤ n, m ≤ 1000\)

分析

此題我們要抓住原題中的一句話:

如果這趟車次停靠了火車站 \(x\),則始發站、終點站之間所有級別大於等於火車站\(x\) 的都必須停靠。

反過來也就是說:

在一個車次中,停下來的車站一定比沒停下來的車站的級別高。

現在讓你求最少分為多少級,也就是說,我們用 \(1, 2, 3, 4\) 給級別編號,程式讓我們求的就是最高的那個級別。

既然在一個車次中停下來的車站一定比沒停下來的車站的級別高,我們就可以根據這個讓級別低的向級別高的連邊,最終就會形成一個DAG。對於這個DAG進行topsort,並同時進行遞推,便可以得出每一個車站的等級了,最後取等級最大值即可。

上程式碼。

程式碼

/*
 * @Author: crab-in-the-northeast 
 * @Date: 2020-10-01 09:14:56 
 * @Last Modified by: crab-in-the-northeast
 * @Last Modified time: 2020-10-01 11:32:31
 */
#include <iostream>
#include <cstdio>
#include <vector>
#include <queue>

const int maxn = 1005;
const int maxm = 1005;

std :: vector <int> G[maxn];
int ind[maxn];
bool vis[maxn][maxn];

int n, m;
int topsort() {
    std :: queue <std :: pair <int, int> > q;
    int ans = 1;
    for (int i = 1; i <= n; ++i)
        if (ind[i] == 0)
            q.push(std :: make_pair(i, 1));

    while (!q.empty()) {
        int u = q.front().first, level = q.front().second;
        q.pop();
        for (int i = 0; i < G[u].size(); ++i) {
            int v = G[u][i];
            --ind[v];
            if (ind[v] == 0) {
                q.push(std :: make_pair(v, level + 1));
                ans = ans > level + 1 ? ans : level + 1;
            }
        }
    }

    return ans;
}

int main() {
    std :: scanf("%d %d", &n, &m);

    for (int i = 1; i <= m; ++i) {
        int s;
        std :: scanf("%d", &s);
        int stop[maxn];
        bool is_stop[maxn] = {false};
        for (int j = 1; j <= s; ++j) {
            std :: scanf("%d", &stop[j]);
            is_stop[stop[j]] = true;
        }

        for (int j = stop[1]; j <= stop[s]; ++j) {
            if (!is_stop[j]) {
                for (int k = 1; k <= s; ++k) {
                    if (!vis[j][stop[k]]) {
                        ++ind[stop[k]];
                        G[j].push_back(stop[k]);
                        vis[j][stop[k]] = true;
                    }
                }
            }
        }
    }

    std :: printf("%d\n", topsort());
    return 0;
}

評測記錄

評測記錄