日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

luogu 4768

發布時間:2025/3/15 编程问答 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 luogu 4768 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

kruskal 重構樹
對于一張無向圖,我們在進行 kruskal 的過程中
每當合并兩個聯通塊時
新建虛擬節點 t
對于兩個聯通塊的根節點 fau,fav 連無向邊
(fau, t),(fav, t) 其中點 t 的點權為兩個聯通塊當前連邊的邊權
對于這道題
首先 dijkstra 處理所有點到1號點的最短路
然后按照邊的海拔進行降序排序
這樣做出重構樹之后
顯然對于點 u,它的所有子樹中的相關的邊的海拔(這里已經轉化為了虛擬節點的點權)都要大于該點的海拔
這樣的話
對于詢問二元組 x, h
倍增將 x 調到海拔最低且高于 h 的點處
此時 x 的子樹中dis[]的最小值即為此次詢問的結果
注意:在進行重構樹時
虛擬節點的dis[]每次可以取 min(dis[fau], dis[fav])
這樣就相當于dis[t]表示 t 的子樹中dis[]的最小值
省去了一遍 dfs

#include <iostream> #include <cstdio> #include <algorithm> #include <queue> #include <cstring>using namespace std; const int N = 4e5 + 10, oo = 1e9 + 7;struct Node {int u, v, len, high, nxt; } E[N], G[N << 2], Edge[N << 1]; struct Node_ {int u, dis_;inline bool operator < (const Node_ a) const {return dis_ > a.dis_;} };int head_1[N], head_2[N << 1], now; int dis[N << 1]; bool vis[N]; int fa[N << 1]; int n, m; int High[N << 1]; int f[N << 1][30]; int deep[N << 1];#define gc getchar() inline int read() {int x = 0;char c = gc;while(c < '0' || c > '9') c = gc;while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = gc;return x; }int Get(int x) {return fa[x] == x ? x : fa[x] = Get(fa[x]);} inline bool Cmp(Node a, Node b) {return a.high > b.high;} void Dfs(int u, int fa) {for(int i = head_2[u]; ~ i; i = G[i].nxt) if(G[i].v != fa) f[G[i].v][0] = u, Dfs(G[i].v, u);} inline int Jump(int X, int H) {for(int i = 20; i >= 0; i --) if(f[X][i] && High[f[X][i]] > H) X = f[X][i];return X;} inline void Add_Edge(int u, int v, int Len) {Edge[++ now].v = v; Edge[now].len = Len; Edge[now].nxt = head_1[u]; head_1[u] = now;} inline void Add_G(int u, int v) {G[++ now].v = v; G[now].nxt = head_2[u]; head_2[u] = now;} inline void Pre() {for(int i = 1; i <= 20; i ++) for(int j = 1; j <= (n * 2 - 1); j ++) f[j][i] = f[f[j][i - 1]][i - 1];}inline void Dijkstra() {for(int i = 1; i <= n; i ++) dis[i] = oo;for(int i = 1; i <= n; i ++) vis[i] = 0;priority_queue <Node_> Q;Q.push((Node_) {1, 0});dis[1] = 0;while(!Q.empty()) {Node_ topp = Q.top();Q.pop();if(vis[topp.u]) continue;vis[topp.u] = 1;for(int i = head_1[topp.u]; ~ i; i = Edge[i].nxt)if(dis[Edge[i].v] > dis[topp.u] + Edge[i].len) {dis[Edge[i].v] = dis[topp.u] + Edge[i].len;Q.push((Node_) {Edge[i].v, dis[Edge[i].v]});}} }inline void Kruskal() {sort(E + 1, E + m + 1, Cmp);for(int i = 1; i <= (n << 1); i ++) fa[i] = i;for(int i = 1; i <= (n << 1); i ++) head_2[i] = -1;int cnt = n;now = 0;for(int i = 1; i <= m; i ++) {if(cnt == n * 2 - 1) break;int u = E[i].u, v = E[i].v, fau = Get(u), fav = Get(v);if(fau != fav) {fa[fau] = fa[fav] = ++ cnt;High[cnt] = E[i].high;dis[cnt] = min(dis[fau], dis[fav]);Add_G(fau, cnt), Add_G(cnt, fau), Add_G(fav, cnt), Add_G(cnt, fav);}} }int main() {for(int T = read(); T; T --) {memset(f, 0, sizeof f);n = read(), m = read(); now = 0;for(int i = 1; i <= n; i ++) head_1[i] = -1;for(int i = 1; i <= m; i ++) {int u = read(), v = read(), Len = read(), high = read();Add_Edge(u, v, Len), Add_Edge(v, u, Len);E[i] = (Node) {u, v, Len, high};}Dijkstra(), Kruskal(), Dfs(2 * n - 1, 0), Pre();int Q = read(), K = read(), S = read(), Lastans = 0;for(; Q; Q --) {int X = (read() + K * Lastans - 1) % n + 1, H = (read() + K * Lastans) % (S + 1);Lastans = dis[Jump(X, H)]; cout << Lastans << "\n";}}return 0; }

?

轉載于:https://www.cnblogs.com/shandongs1/p/9497615.html

總結

以上是生活随笔為你收集整理的luogu 4768的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。