1. 程式人生 > >Luogu1967 NOIP2013D1T3 貨車運輸 最大生成樹、倍增

Luogu1967 NOIP2013D1T3 貨車運輸 最大生成樹、倍增

生成 bool tchar problem digi || getchar() class getchar

傳送門

題意:給出一個$N$個節點、$M$條邊的圖,$Q$次詢問,每一次詢問兩個點之間的所有可行路徑中經過的邊的邊權的最小值中的最大值。$N \leq 10000 , M \leq 50000 , Q \leq 30000$


很套路的題目,沒什麽好說的,最大生成樹上倍增求一段以內的最短邊,然後每一次詢問跳$LCA$即可。

註意:圖可能是不連通的,所以在跳$LCA$之前要判斷一下是否在一個連通塊內。

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 inline int read(){
 4     int a = 0;
 5     char c = getchar();
6 while(!isdigit(c)) c = getchar(); 7 while(isdigit(c)) a = (a << 3) + (a << 1) + (c ^ 0) , c = getchar(); 8 return a; 9 } 10 vector < int > tree[10001] , w[10001]; 11 int pro[30001][3] , head , depth[10001] , father[10001] , dad[10001] , wei[10001]; 12 struct Edge{ 13 int start , end , w;
14 }Ed[50001]; 15 bool cmpforEdge(Edge a , Edge b){return a.w > b.w;} 16 int find(int a){return father[a] == a ? a : (father[a] = find(father[a]));} 17 inline int min(int a , int b){return a < b ? a : b;} 18 void LCA(int t , int pa){ 19 depth[t] = depth[dad[t] = pa] + 1; 20 for(int i = 0 ; i < tree[t].size() ; i++)
21 if(!depth[tree[t][i]]){ 22 wei[tree[t][i]] = w[t][i]; 23 LCA(tree[t][i] , t); 24 } 25 } 26 inline int goLCA(int a , int b){ 27 int minN = 100001; 28 while(a != b) 29 if(depth[a] > depth[b]){ 30 minN = min(minN , wei[a]); 31 a = dad[a]; 32 } 33 else{ 34 minN = min(minN , wei[b]); 35 b = dad[b]; 36 } 37 return minN; 38 } 39 int main(){ 40 int N = read() , M = read(); 41 for(int i = 1 ; i <= N ; i++) father[i] = i; 42 for(int i = 0 ; i < M ; i++) 43 Ed[i].start = read() , Ed[i].end = read() , Ed[i].w = read(); 44 sort(Ed , Ed + M , cmpforEdge); 45 for(int i = 0 ; i < M ; i++) 46 if(find(Ed[i].start) - find(Ed[i].end)){ 47 father[find(Ed[i].start)] = find(Ed[i].end); 48 tree[Ed[i].start].push_back(Ed[i].end); 49 tree[Ed[i].end].push_back(Ed[i].start); 50 w[Ed[i].start].push_back(Ed[i].w); 51 w[Ed[i].end].push_back(Ed[i].w); 52 } 53 int num = read(); 54 for(int i = 0 ; i < num ; i++) pro[i][0] = read() , pro[i][1] = read(); 55 for(int i = 1 ; i <= N ; i++) 56 if(!depth[i]){ 57 head = 0; 58 LCA(i , 0); 59 for(int j = 0 ; j < num ; j++) 60 if(!pro[j][2]) 61 if(find(pro[j][0]) == find(i) && find(pro[j][1]) == find(i)) 62 pro[j][2] = goLCA(pro[j][0] , pro[j][1]); 63 else if(find(pro[j][0]) == find(i) || find(pro[j][1]) == find(i)) 64 pro[j][2] = -1; 65 } 66 for(int i = 0 ; i < num ; i++) printf("%d\n" , pro[i][2]); 67 return 0; 68 }

Luogu1967 NOIP2013D1T3 貨車運輸 最大生成樹、倍增