[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 }