constint N = 1e5+10; int h[N], e[N], ne[N], idx, d[N]; int n, m; int q[N];
voidadd(int a, int b){ e[idx] = b, ne[idx] = h[a], h[a] = idx++; // 入度 d[b]++; }
booltopsort(){ int tt = -1, hh = 0; for (int i = 1; i <= n; i++) { // 这里是 d[i] 代表第 i 节点的入度 所以从 1 ~ n 而不是从 0 开始 if (d[i] == 0) q[++tt] = i; } while (hh <= tt) { int t = q[hh++]; for (int i = h[t]; i != -1; i = ne[i]) { int j = e[i]; d[j]--; // 添加到队列中的是树的节点 if (d[j] == 0) q[++tt] = j; } } // 如果所有节点都被遍历过,那么拓扑序列是存在的 return tt == n-1; }
intmain(){ memset(h, -1, sizeof h); cin >> n >> m; int a, b; for (int i = 0; i < m; i++) { cin >> a >> b; add(a, b); } if (topsort()) { for (int i = 0; i < n; i++) cout << q[i] << ' '; } elseputs("-1"); }
typedeflonglong LL; constint N = 200010, M = 1200010, P = 998244353; int topo[N]; int h[N], e[M], ne[M], cnt[N], add[N], mul[N], type[N], din[N], p[N], idx; int val[N/2]; int n, m, q;
voidaddedge(int a, int b){ e[idx] = b, ne[idx] = h[a], h[a] = idx++; din[b]++; }
voidtopsort(){ int hh = 0, tt = -1; for (int i = 0; i <= n+m; i++) { if (din[i] == 0) topo[++tt] = i; }
while (hh <= tt) { int t = topo[hh++]; for (int i = h[t]; ~i; i = ne[i]) { int j = e[i]; if (--din[j] == 0) topo[++tt] = j; } } }
voidpushup(){ for (int i = n+m; ~i; i--) { int u = topo[i]; for (int i = h[u]; ~i; i = ne[i]) { int j = e[i]; mul[u] = (LL)mul[u] * mul[j] % P; } } }
voidpushdown(){ for (int i = 0; i <= n+m; i++) { LL prod = 1; int u = topo[i]; for (int i = h[u]; ~i; i = ne[i]) { int j = e[i]; cnt[j] = (cnt[j] + prod * cnt[u]) % P; prod = prod * mul[j] % P; } } }
scanf("%d", &m); fill(mul, mul+n+m+1, 1); for (int i = 1; i <= m; i++) { int u = i+n; scanf("%d", &type[u]); if (type[u] == 1) scanf("%d%d", &p[u], &add[u]); if (type[u] == 2) scanf("%d", &mul[u]); if (type[u] == 3) { int c, f; scanf("%d", &c); while (c--) { scanf("%d", &f); addedge(u, f+n); } } }
scanf("%d", &q); for (int i = 1, f; i <= q; i++) { scanf("%d", &f); addedge(0, f+n); }
cnt[0] = 1; topsort(); pushup(); pushdown();
for (int i = 0; i <= n+m; i++) if (type[i] == 1) val[p[i]] = (val[p[i]] + (LL)add[i] * cnt[i]) % P;
for (int i = 1; i <= n; i++) printf("%d ", val[i]); puts("");
return0; }
[NOIP2013] 车站分级
一条单向的铁路线上,依次有编号为 1,2,…,n 个火车站。
每个火车站都有一个级别,最低为 1 级。
现有若干趟车次在这条线路上行驶,每一趟都满足如下要求:如果这趟车次停靠了火车站 x,则始发站、终点站之间所有级别大于等于火车站 x 的都必须停靠。(注意:起始站和终点站自然也算作事先已知需要停靠的站点) 。
constint N = 2010, M = 1000010; int n, m; int h[N], e[M], ne[M], w[M], din[N], dist[N], idx; bool st[N]; int q[N];
intread(){ int x = 0; char ch = getchar(); while (ch < '0' || ch > '9') ch = getchar(); while ('0' <= ch && ch <= '9') { x = x*10 + (ch & 15); ch = getchar(); } return x; }
voidadd(int a, int b, int c){ e[idx] = b, ne[idx] = h[a], w[idx] = c, h[a] = idx++; din[b]++; }
voidtopsort(){ int hh = 0, tt = -1; for (int i = 1; i <= m+n; i++) { if (din[i] == 0) q[++tt] = i, dist[i] = 1; } while (hh <= tt) { int t = q[hh++]; for (int i = h[t]; ~i; i = ne[i]) { int j = e[i]; if (--din[j] == 0) q[++tt] = j; } } }
intsolve(){ for (int i = 0; i < m+n; i++) { int t = q[i]; for (int j = h[t]; ~j; j = ne[j]) { int k = e[j]; dist[k] = max(dist[k], dist[t] + w[j]); } } return *max_element(dist+1, dist+1+n); }
intmain(){ n = read(), m = read(); memset(h, -1, sizeof h); for (int i = 1; i <= m; i++) { memset(st, 0, sizeof st); int cnt = read(); int start = n, end = 0; while (cnt--) { int x = read(); st[x] = true; start = min(start, x), end = max(end, x); } int v = n+i; for (int j = start; j <= end; j++) if (st[j]) add(v, j, 0); elseadd(j, v, 1); } topsort(); printf("%d\n", solve()); return0; }