[NOIP2013]车站分级

原题传送门

这道题根据题意,能得出该结论:

·一条线路经过的站点,停靠站点等级一定大于未停靠的站点

又因为输入保证所有的车次都满足要求,所以满足偏序集关系。我们可以将站点的大小关系用$DAG$图表示,即将一条线路中停靠站点向未停靠站点连有向边。最后求一遍DAG图中最长链。

问题在于构图的复杂度为$O(n^2m)$,无法接受。

这里采用构建虚点的方式解决构图问题,如下图

此时复杂度为$O(nm)$。

最后注意最长链包括了虚点,把它去掉即可。

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <algorithm>
 5 #include <queue>
 6 
 7 using namespace std;
 8 
 9 #define re register
10 #define rep(i, a, b) for (re int i = a; i <= b; ++i)
11 #define repd(i, a, b) for (re int i = a; i >= b; --i)
12 #define maxx(a, b) a = max(a, b);
13 #define minn(a, b) a = min(a, b);
14 #define LL long long
15 #define inf (1 << 30)
16 
17 inline int read() {
18     int w = 0, f = 1; char c = getchar();
19     while (!isdigit(c)) f = c == '-' ? -1 : f, c = getchar();
20     while (isdigit(c)) w = (w << 3) + (w << 1) + (c ^ '0'), c = getchar();
21     return w * f;
22 }
23 
24 queue<int> q, q0, empty;
25 
26 const int maxn = 1e3 + 5;
27 
28 int a[maxn][maxn], e[maxn << 1][maxn << 1], n, m, r[maxn], d[maxn << 1], ans;
29 
30 int main() {
31     n = read(), m = read();
32 
33     rep(i, 1, m) {
34         a[i][0] = read();
35         memset(r, 0, sizeof(r));
36         rep(j, 1, a[i][0]) a[i][j] = read(), r[a[i][j]] = 1;
37         rep(j, a[i][1], a[i][a[i][0]]) if (r[j]) e[j][n+i] = 1; else e[n+i][j] = 1;
38     }
39 
40     rep(i, 1, n+m) {
41         rep(j, 1, n+m)
42             d[i] += e[j][i] ? 1 : 0;
43         if (!d[i]) q.push(i);
44     }
45 
46     while (!q.empty()) {
47         while (!q.empty()) {
48             int u = q.front(); q.pop();
49             rep(i, 1, n+m) if (e[u][i]) {
50                 d[i]--;
51                 if (!d[i]) q0.push(i);
52             }
53         }
54         q = q0; q0 = empty;
55         ans++;
56     }
57 
58     printf("%d", (ans + 1) >> 1);
59 
60     return 0;
61 }

猜你喜欢

转载自www.cnblogs.com/ac-evil/p/10323679.html