NOI 2018 歸程 Kruskal 重構樹

2022-05-09 16:19:02 字數 1105 閱讀 7074

題解

kruskal重構樹:每次一條邊連線兩個集合,建乙個新點,點權為該邊邊權;把這兩個集合的根連向新點。

性質:(如果求的是最大生成樹)葉子結點是圖中實際結點;葉子到根路徑上點權遞減;兩點間lca的權值就是這兩點走最大生成樹經過的最小邊

然後對於這題我們建重構樹然後每次倍增找到乙個深度極小的祖先u,返回u子樹內實結點dis的最小值即可

#include #include #include using namespace std;

typedef long long ll;

const int n = 4e5 + 10;

const ll inf = 1e15;

int n, m, q, k, s;

struct edge e[n * 2];

int hd[n], c;

ll d[n];

void add(int u, int v, int w) ; hd[u] = c ++;

}struct node

};void dijkstra() );

while(pq.size()) );

}} }

}struct edge2

} e2[n];

int f[n], t[n], p[n][22], w[n], nn;

ll dt[n];

int find(int u)

void kruskal()

} for(int j = 1; j <= 20; j ++)

for(int i = 1; i <= nn; i ++)

p[i][j] = p[p[i][j - 1]][j - 1];

}ll qry(int u, int low)

} return dt[v];

}void solve() ;

} dijkstra();

kruskal();

scanf("%d%d%d", &q, &k, &s);

ll lans = 0;

for(int i = 1; i <= q; i ++)

}int main()

NOI2018 歸程 題解

容易發現,當水位線確定了,圖會被分成若干個連通塊,連通塊裡的點可以互相到達,故連通塊內點的答案為其中的點到 1 的距離的最小值,這個可以先 dijkstra 預處理求出 spfa 死了 那考慮怎麼維護連通塊。可持久化並查集?感覺不好搞,有一種神奇的演算法 kruscal 重構樹。其實就是 krusc...

NOI 2018 歸程 Kruskal重構樹

題目大意 太長了,略 kruskal重構樹,很神奇的乙個演算法吧 如果兩個並查集被某種條件合併,那麼這個條件作為乙個新的節點連線兩個並查集 那麼在接下來的提問中,如果某個點合法,它的所有子節點也都合法,即子節點的限制少於父節點 include include include include defi...

NOI2018 歸程(kruskal重構樹)

思路 每天的最短距離相當於每天走高於海拔高於水位線的路所能到達的所有點中到1的最短距離。現在要想辦法能夠直接查詢這個最短距離,如果能根據海拔構造一種樹狀結構,那麼每次能開車到達的點對應一顆子樹,那麼只需要倍增出這顆子樹的根節點就可以了。kruskal重構樹 對海拔從大到小排序,然後跑kruskal,...