Loading docs/graph/steiner-tree.md +126 −128 Original line number Diff line number Diff line Loading @@ -74,7 +74,8 @@ void dijkstra(int s) { memset(vis, 0, sizeof(vis)); while (!q.empty()) { P item = q.top(); q.pop(); P item = q.top(); q.pop(); if (vis[item.second]) continue; vis[item.second] = 1; for (int i = head[item.second]; i; i = e[i].next) { Loading @@ -84,7 +85,6 @@ } } } } int main() { Loading @@ -93,8 +93,10 @@ int u, v, w; for (int i = 1; i <= m; i++) { scanf("%d %d %d", &u, &v, &w); add(u, v, w); tree[tot] = v; add(v, u, w); tree[tot] = u; add(u, v, w); tree[tot] = v; add(v, u, w); tree[tot] = u; } for (int i = 1; i <= k; i++) { scanf("%d", &key[i]); Loading @@ -104,8 +106,7 @@ for (int i = 1; i <= n; i++) { for (int subs = s & (s - 1); subs; subs = s & (subs - 1)) dp[i][s] = min(dp[i][s], dp[i][subs] + dp[i][s ^ subs]); if (dp[i][s] != INF) q.push(P(dp[i][s], i)); if (dp[i][s] != INF) q.push(P(dp[i][s], i)); } dijkstra(s); } Loading @@ -114,9 +115,9 @@ } ``` 另外一道经典例题[[WC2008]游览计划](https://www.luogu.com.cn/problem/P4294)。 另外一道经典例题 [\[WC2008\] 游览计划](https://www.luogu.com.cn/problem/P4294) 。 这道题是求点权和最小的斯坦纳树,用$f(i,S)$表示以$i$为根的一棵树,包含集合$S$中所有点的最小点权值和。$a_i$表示点权。 这道题是求点权和最小的斯坦纳树,用 $f(i,S)$ 表示以 $i$ 为根的一棵树,包含集合 $S$ 中所有点的最小点权值和。 $a_i$ 表示点权。 考虑状态转移: Loading Loading @@ -147,21 +148,19 @@ queue<P> q; bool legal(P u) { if (u.first >= 0 && u.second >= 0 && u.first < n && u.second < m) {return true;} if (u.first >= 0 && u.second >= 0 && u.first < n && u.second < m) { return true; } return false; } int num(P u) { return u.first * m + u.second; } int num(P u) { return u.first * m + u.second; } void spfa(int s) { memset(inq, 0, sizeof(inq)); while (!q.empty()) { P u = q.front(); q.pop(); P u = q.front(); q.pop(); inq[num(u)] = 0; for (int d = 0; d < 4; d++) { P v = mp(u.first + dx[d], u.second + dy[d]); Loading @@ -182,8 +181,7 @@ if (!pre[num(u)][s].second) return; ans[u.first][u.second] = 1; int nu = num(u); if(pre[nu][s].first == u) dfs(u, s ^ pre[nu][s].second); if (pre[nu][s].first == u) dfs(u, s ^ pre[nu][s].second); dfs(pre[nu][s].first, pre[nu][s].second); } Loading @@ -203,15 +201,13 @@ } for (int s = 1; s < (1 << K); s++) { for (int i = 0; i < n * m; i++) { for (int subs = s & (s - 1); subs; subs = s & (subs - 1)) { for (int subs = s & (s - 1); subs; subs = s & (subs - 1)) { if (f[i][s] > f[i][subs] + f[i][s ^ subs] - a[i]) { f[i][s] = f[i][subs] + f[i][s ^ subs] - a[i]; pre[i][s] = mp(mp(i / m, i % m), subs); } } if (f[i][s] < INF) q.push(mp(i / m, i % m) ); if (f[i][s] < INF) q.push(mp(i / m, i % m)); } spfa(s); } Loading @@ -219,8 +215,10 @@ dfs(mp(root / m, root % m), (1 << K) - 1); for (int i = 0, tot = 0; i < n; i++) { for (int j = 0; j < m; j++) { if(!a[tot ++]) putchar('x'); else putchar(ans[i][j] ? 'o' : '_'); if (!a[tot++]) putchar('x'); else putchar(ans[i][j] ? 'o' : '_'); } if (i != n - 1) printf("\n"); } Loading @@ -232,8 +230,8 @@ [【模板】最小斯坦纳树](https://www.luogu.com.cn/problem/P6192) [[WC2008]游览计划](https://www.luogu.com.cn/problem/P4294) [\[WC2008\] 游览计划](https://www.luogu.com.cn/problem/P4294) [ [JLOI2015]管道连接](https://loj.ac/problem/2110) [\[JLOI2015\] 管道连接](https://loj.ac/problem/2110) [ [APIO2013]机器人](https://www.luogu.com.cn/problem/P3638) [\[APIO2013\] 机器人](https://www.luogu.com.cn/problem/P3638) Loading
docs/graph/steiner-tree.md +126 −128 Original line number Diff line number Diff line Loading @@ -74,7 +74,8 @@ void dijkstra(int s) { memset(vis, 0, sizeof(vis)); while (!q.empty()) { P item = q.top(); q.pop(); P item = q.top(); q.pop(); if (vis[item.second]) continue; vis[item.second] = 1; for (int i = head[item.second]; i; i = e[i].next) { Loading @@ -84,7 +85,6 @@ } } } } int main() { Loading @@ -93,8 +93,10 @@ int u, v, w; for (int i = 1; i <= m; i++) { scanf("%d %d %d", &u, &v, &w); add(u, v, w); tree[tot] = v; add(v, u, w); tree[tot] = u; add(u, v, w); tree[tot] = v; add(v, u, w); tree[tot] = u; } for (int i = 1; i <= k; i++) { scanf("%d", &key[i]); Loading @@ -104,8 +106,7 @@ for (int i = 1; i <= n; i++) { for (int subs = s & (s - 1); subs; subs = s & (subs - 1)) dp[i][s] = min(dp[i][s], dp[i][subs] + dp[i][s ^ subs]); if (dp[i][s] != INF) q.push(P(dp[i][s], i)); if (dp[i][s] != INF) q.push(P(dp[i][s], i)); } dijkstra(s); } Loading @@ -114,9 +115,9 @@ } ``` 另外一道经典例题[[WC2008]游览计划](https://www.luogu.com.cn/problem/P4294)。 另外一道经典例题 [\[WC2008\] 游览计划](https://www.luogu.com.cn/problem/P4294) 。 这道题是求点权和最小的斯坦纳树,用$f(i,S)$表示以$i$为根的一棵树,包含集合$S$中所有点的最小点权值和。$a_i$表示点权。 这道题是求点权和最小的斯坦纳树,用 $f(i,S)$ 表示以 $i$ 为根的一棵树,包含集合 $S$ 中所有点的最小点权值和。 $a_i$ 表示点权。 考虑状态转移: Loading Loading @@ -147,21 +148,19 @@ queue<P> q; bool legal(P u) { if (u.first >= 0 && u.second >= 0 && u.first < n && u.second < m) {return true;} if (u.first >= 0 && u.second >= 0 && u.first < n && u.second < m) { return true; } return false; } int num(P u) { return u.first * m + u.second; } int num(P u) { return u.first * m + u.second; } void spfa(int s) { memset(inq, 0, sizeof(inq)); while (!q.empty()) { P u = q.front(); q.pop(); P u = q.front(); q.pop(); inq[num(u)] = 0; for (int d = 0; d < 4; d++) { P v = mp(u.first + dx[d], u.second + dy[d]); Loading @@ -182,8 +181,7 @@ if (!pre[num(u)][s].second) return; ans[u.first][u.second] = 1; int nu = num(u); if(pre[nu][s].first == u) dfs(u, s ^ pre[nu][s].second); if (pre[nu][s].first == u) dfs(u, s ^ pre[nu][s].second); dfs(pre[nu][s].first, pre[nu][s].second); } Loading @@ -203,15 +201,13 @@ } for (int s = 1; s < (1 << K); s++) { for (int i = 0; i < n * m; i++) { for (int subs = s & (s - 1); subs; subs = s & (subs - 1)) { for (int subs = s & (s - 1); subs; subs = s & (subs - 1)) { if (f[i][s] > f[i][subs] + f[i][s ^ subs] - a[i]) { f[i][s] = f[i][subs] + f[i][s ^ subs] - a[i]; pre[i][s] = mp(mp(i / m, i % m), subs); } } if (f[i][s] < INF) q.push(mp(i / m, i % m) ); if (f[i][s] < INF) q.push(mp(i / m, i % m)); } spfa(s); } Loading @@ -219,8 +215,10 @@ dfs(mp(root / m, root % m), (1 << K) - 1); for (int i = 0, tot = 0; i < n; i++) { for (int j = 0; j < m; j++) { if(!a[tot ++]) putchar('x'); else putchar(ans[i][j] ? 'o' : '_'); if (!a[tot++]) putchar('x'); else putchar(ans[i][j] ? 'o' : '_'); } if (i != n - 1) printf("\n"); } Loading @@ -232,8 +230,8 @@ [【模板】最小斯坦纳树](https://www.luogu.com.cn/problem/P6192) [[WC2008]游览计划](https://www.luogu.com.cn/problem/P4294) [\[WC2008\] 游览计划](https://www.luogu.com.cn/problem/P4294) [ [JLOI2015]管道连接](https://loj.ac/problem/2110) [\[JLOI2015\] 管道连接](https://loj.ac/problem/2110) [ [APIO2013]机器人](https://www.luogu.com.cn/problem/P3638) [\[APIO2013\] 机器人](https://www.luogu.com.cn/problem/P3638)