給出一張圖,給出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。輸入檔案第一行有兩個用乙個空格隔...