文章目录
洛谷 P1983 [NOIP2013 普及组] 车站分级
解题思路
这道题是一道非常经典的建模为拓扑排序解决的实际问题。可以想到,如果不同的事物之间有从高到低的优先级关系,那么可以用一条从低优先级点连向高优先级点(或反过来)的边来表示这一种相对关系。根据这个思路,我们很容易想到如何去建图:低优先级的站点连一条边到高优先级的站点。
可以发现,当一列火车从 s s s到 t t t行驶的过程中,那些停靠的站点的优先级肯定要大于未停靠的站点。发现这一条规律以后其实这道题已经解决了。对于每一个列车运行的信息,都从所有未停靠的站点分别连一条边到所有停靠的站点。然后在形成的DAG上跑拓扑排序找到最长的路径即为答案。时间复杂度应为 O ( n m ) O(nm) O(nm)。
Attention:注意到本题的边数量较多,考虑使用邻接矩阵存图(用邻接表可能会像我一样t到飞起)
AC代码
实现拓扑排序找到最长路径的方法有很多种,例如bfs一层一层删点和边,但我的代码中使用的是记忆化搜索的方式。
#include <bits/stdc++.h>
using namespace std;
#define endl '\n'
#define IOS ios::sync_with_stdio(0); cin.tie(0); cout.tie(0)
#define pb push_back
#define Yes cout << "Yes\n"
#define No cout << "No\n"
#define YES cout << "YES\n"
#define NO cout << "NO\n"
#define ff first
#define ss second
#define fori(x,y) for(int i=x;i<=(int)(y);++i)
#define forj(x,y) for(int j=x;j<=(int)(y);++j)
#define fork(x,y) for(int k=x;k<=(int)(y);++k)
#define debug(x) cout << #x << " = " << x << endl
typedef long long ll;
typedef pair<int,int> pii;
typedef pair<ll,ll> pll;
ll MOD = 998244353;
ll qpow(ll a,ll p) {
ll res=1; while(p) {
if (p&1) {
res=res*a%MOD;} a=a*a%MOD; p>>=1;} return res;}
const int N = 1e3+7;
int g[N][N];
int deg[N];
int n, q;
int dep[N];
int dfs(int u) {
if (dep[u]) return dep[u];
int res = 0;
fori(1, n) if (g[u][i]) {
res = max(res, dfs(i));
}
return (dep[u] = res+1);
}
bool is[N];
void solve() {
cin >> n >> q;
while (q--) {
int m; cin >> m;
fori(1, n) is[i] = false;
int s, t;
vector<int> vec;
fori(1, m) {
int x; cin >> x;
if (i == 1) s = x;
else if (i == m) t = x;
is[x] = true;
vec.push_back(x);
}
fori(s, t) if (!is[i]) {
for (auto v: vec) {
if (g[i][v]) continue;
g[i][v] = 1;
deg[v]++;
}
}
}
int ma = 1;
fori(1, n) if (deg[i] == 0) ma = max(ma, dfs(i));
cout << ma << endl;
}
signed main(