codevs 1218 疫情控制
生活随笔
收集整理的這篇文章主要介紹了
codevs 1218 疫情控制
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
題意:
一棵有n個點的樹,樹上有m個障礙在給定的位置,現在需要移動這m個障礙,使得從根節點出發的任意路徑不能到達任意一個葉子節點(不能放在根節點上),求移動的最小花費。
?
題解:
首先需要明白的有這幾點:
① 如果一個點所有的兒子都被阻礙了,那么這個點也會被阻礙,那么現在的問題就是覆蓋根所有的兒子節點。
② 若在規定的時間移動這m個點,那么這m個點越往上移動越優越。
③ 若在規定的時間移動這m個點,那么一定會出現兩種情況,第一種不能越過根節點,第二種能夠越過根節點。
?
現在需要解決一下問題:
1.怎么解決規定的時間,可以二分一個時間。
2.怎么在很小的復雜度使得m個點盡量的往上跳,倍增
3.怎么處理那兩種情況?
首先處理不能越過根節點的情況,盡量的往上跳,把到達極限的點標記,然后將所有的標記根據①的原理上傳到根的兒子。
然后處理能夠越過根節點的情況,記錄下每個能夠越過根節點的點剩余的時間 t 和屬于哪條路徑的根的兒子的編號 id,記錄下需要被其他路徑的點覆蓋的根的兒子的編號,然后貪心覆蓋就好了。。。
?
代碼:
#include <cstdio> #include <cstring> #include <iostream> #include <algorithm> using namespace std;const int N = 5e4 + 7; struct edge {int v, nxt, w;}e[N<<1]; struct node {int w, id;} g[N], f[N]; int anc[20][N], cos[20][N], ecnt, head[N], vis[N], n, m, army[N];void adde (int u, int v, int w) {e[ecnt].v = v;e[ecnt].w = w;e[ecnt].nxt = head[u];head[u] = ecnt++; }void DFS (int u, int pre) {for (int it = head[u]; it != -1; it = e[it].nxt) {int v = e[it].v;if (v == pre) continue;anc[0][v] = u;cos[0][v] = e[it].w;for (int i = 1; i <= 18; ++i) {anc[i][v] = anc[i-1][anc[i-1][v]];cos[i][v] = cos[i-1][v] + cos[i-1][anc[i-1][v]];}DFS(v, u);} }bool cmp (node a, node b) {return a.w < b.w;}void pushup (int u, int pre) {int isleaf = 1, flag = 1;for (int it = head[u]; it != -1; it = e[it].nxt) {int v = e[it].v;if (v == pre) continue;pushup(v, u);if (!vis[v]) flag = 0;isleaf = 0;}if (flag && !isleaf && u != 1) vis[u] = 1; }int check (int x) {int cntg = 0, cntf = 0;memset (vis, 0, sizeof vis);for (int i = 1; i <= m; ++i) {int p = army[i], t = x;for (int j = 18; j >= 0; --j) {if (anc[j][p] && t >= cos[j][p]) {t -= cos[j][p];p = anc[j][p];}}if (p == 1) {p = army[i];for (int j = 18; j >= 0; --j)if (anc[j][p] > 1) p = anc[j][p];g[++cntg] = (node){t, p};}else vis[p] = 1;}pushup(1, 0);for (int it = head[1]; it != -1; it = e[it].nxt) {int v = e[it].v;if (!vis[v]) f[++cntf] = (node){e[it].w, v};}sort (g + 1, g + 1 + cntg, cmp);sort (f + 1, f + 1 + cntf, cmp);int cur = 1;f[cntf+1] = (node){1e9 + 7, 0};for (int i = 1; i <= cntg; ++i) {if (!vis[g[i].id]) vis[g[i].id] = 1;else if (g[i].w >= f[cur].w) vis[f[cur].id] = 1;while (vis[f[cur].id]) cur++;}return cur > cntf; }int main () {memset (head, -1, sizeof head);scanf ("%d", &n);for (int i = 1; i < n; ++i) {int u, v, w;scanf ("%d%d%d", &u, &v, &w);adde (u, v, w);adde (v, u, w);}DFS (1, 0);scanf ("%d", &m);for (int i = 1; i <= m; ++i) scanf ("%d", &army[i]);int l = 0, r = 1e9 + 7;while (l < r) {int mid = l + r >> 1;if (check(mid)) r = mid;else l = mid + 1;}if (l == 1e9 + 7) puts("-1");else printf ("%d\n", l);return 0; }
總結:
遇到問題不要慌張~慢慢分析,首先不要考慮復雜度,直接嘴炮,然后慢慢進行算法上的優化。。。
?
轉載于:https://www.cnblogs.com/xgtao/p/5984858.html
總結
以上是生活随笔為你收集整理的codevs 1218 疫情控制的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 0507
- 下一篇: 还在呼吸致命空气?专业的斐讯空气检测仪,