luogu1967 貨車運輸 最大瓶頸生成樹

2022-06-30 08:15:14 字數 1671 閱讀 8482

給出一張圖,給出q對點,求這兩個點間權值最小邊最大的路徑,輸出這個最小邊權。

我們先一條一條邊建圖。當建立的邊使得圖中形成環時,因為環中的每個節點只考慮是否連通和瓶頸大小,要想互相連通只要一條路就夠了,而只有環上的最小邊和次小邊可能是這條路的瓶頸,且這條路的瓶頸肯定越大越好。故根據貪心,我們可以直接把環中的權值最小邊刪去。

所以我們就維護乙個lct來隨時刪邊增邊,還要用到拆邊等方法來統計路徑上的值嗎?能ac,但太複雜了!

我們從整體考慮,第一段敘述中,每次遇到乙個環,其值為s。由於去掉的是最小邊,邊權w,所以剩餘的路徑上的邊權和s-w是最大的。所以這就是乙個最大生成樹。所以我們就用kruskal演算法求出最大生成樹,再由樹上倍增求解即可。注意kruskal處理的是單向邊而不是無向圖,所以先kruskal,再建圖。

#include #include #include #include using namespace std;

const int max_node = 10010, max_edge = 50010 * 2, max_log = 20, inf = 0x3f3f3f3f;

struct node;

struct edge;

struct node _nodes[max_node], *curroot;

int _vcount;

struct edge

edge() {}

}_edges[max_node * 2], tempedges[max_edge];

int _ecount, tempecount;

edge *newedge()

edge *addedge(node *from, node *to, int w)

void build(int uid, int vid, int w)

int log2(int x)

void dfs(node *cur, edge *fromfa)

else

} for (edge *e = cur->head; e; e = e->next)

if (e->to != cur->elder[0])

dfs(e->to, e);

}void dfsstart() }}

int lca(node *deep, node *high)

} if (deep == high)

return ans;

for (int k = log2(deep->depth); k >= 0; k--)

} ans = min(ans, deep->minval[0]);

ans = min(ans, high->minval[0]);

return ans;

}bool cmpedge(edge a, edge b)

node *findfather(node *cur)

void join(node *root1, node *root2)

void kruskal() }}

int main()

kruskal();

dfsstart();

int querycnt;

scanf("%d", &querycnt);

while (querycnt--)

return 0;

}

luogu1967 貨車運輸

題目描述 a 國有 n 座城市,編號從 1 到 n,城市之間有 m 條雙向道路。每一條道路對車輛都有重量限制,簡稱限重。現在有 q 輛貨車在運輸貨物,司機們想知道每輛車在不超過車輛限重的情況下,最多能運多重的貨物。輸入輸出格式 輸入格式 輸入檔名為 truck.in。輸入檔案第一行有兩個用乙個空格隔...

luogu 1967 貨車運輸

題目大意 無向圖上 每次詢問兩個點 尋找一條路徑使這條路徑上的最小值最大 思路 先跑乙個最大生成樹 然後在最大生成樹上每次對每兩個點跑乙個lca 在倍增的同時開乙個陣列a i j 記錄從i個點往上跑j條路裡j條路中的最小值 然後每次lca的時候順便記錄一下就行了 1 include2 include...

luogu1967 貨車運輸

題目描述 a 國有 n 座城市,編號從 1 到 n,城市之間有 m 條雙向道路。每一條道路對車輛都有重量限制,簡稱限重。現在有 q 輛貨車在運輸貨物,司機們想知道每輛車在不超過車輛限重的情況下,最多能運多重的貨物。輸入輸出格式 輸入格式 輸入檔名為 truck.in。輸入檔案第一行有兩個用乙個空格隔...