bzoj3732: Network--kruskal最小生成树+LCA

这是一道写起来比较顺手的题目

没有各种奇怪的细节,基本就是Kruskal和倍增LCA的模板。。

题目大意:对于一个无向带权图,询问两点之间一条路,使得这条路上的最长边最小,输出最小最长边的的值

那么既然要使最长边最短,我们可以先构造一棵最小生成树

由于kruskal已经将边排了序了,所以对于这棵树,每条边都尽量最短了

然后我们再进行lca求出两点路径上的最长边,即为答案

 

 1 #include<stdio.h>
 2 #include<string.h>
 3 #include<algorithm>
 4 using namespace std;
 5 const int maxn = 15010;
 6 struct node{
 7     int u,v,cost,next;    
 8 }e[maxn*4],et[maxn*2];
 9 int head[maxn],n,m,K,tot,logn,u,v;
10 int f[maxn],dep[maxn],fa[maxn][22],mx[maxn][22];
11 
12 void insert(int u, int v, int c){
13     e[++tot].u=u; e[tot].v=v; e[tot].cost=c; e[tot].next=head[u]; head[u]=tot;
14 }
15 
16 bool cmp(node a, node b){
17     return a.cost<b.cost;
18 }
19 
20 int find(int x){
21     return f[x]==x?x:f[x]=find(f[x]);
22 }
23 
24 void MST(){
25     for (int i=1; i<=n; i++) f[i]=i;
26     for (int i=1; i<=m; i++){
27         int fx=find(et[i].u), fy=find(et[i].v);
28         if (fx!=fy){
29             f[fy]=fx;
30             insert(et[i].u,et[i].v,et[i].cost);
31             insert(et[i].v,et[i].u,et[i].cost);
32         }
33     }
34 }
35 
36 void dfs(int u, int f, int d, int cost){
37     dep[u]=d; fa[u][0]=f; mx[u][0]=cost;
38     for (int i=1; i<=logn; i++) fa[u][i]=fa[fa[u][i-1]][i-1];
39     for (int i=1; i<=logn; i++) mx[u][i]=max(mx[u][i-1],mx[fa[u][i-1]][i-1]);
40     for (int i=head[u]; i!=-1; i=e[i].next)
41         if (e[i].v!=f) dfs(e[i].v,u,d+1,e[i].cost);
42 }
43 
44 int lca_max(int u, int v){
45     int ans=0;
46     if (dep[u]>dep[v]) swap(u,v);
47     while (dep[u]<dep[v]){
48         for (int i=logn; i>=0; i--)
49             if (dep[u]<dep[fa[v][i]]){
50                 ans=max(ans,mx[v][i]);
51                 v=fa[v][i];
52             }
53         ans=max(ans,mx[v][0]);
54         v=fa[v][0];
55     }
56     if (u==v) return ans;
57     for (int i=logn; i>=0; i--){
58         if (fa[u][i]!=fa[v][i]){
59             ans=max(ans,max(mx[v][i],mx[u][i]));
60             u=fa[u][i]; v=fa[v][i];
61         }
62     }
63     ans=max(ans,max(mx[u][0],mx[v][0]));
64     return ans;
65 }
66 
67 int main(){
68     scanf("%d%d%d", &n, &m, &K);
69     tot=-1; memset(head,-1,sizeof(head));
70     while ((1<<logn)<n) logn++;
71     for (int i=1; i<=m; i++)
72         scanf("%d%d%d", &et[i].u, &et[i].v, &et[i].cost);
73     sort(et+1,et+1+m,cmp);
74     MST();
75     dfs(1,0,1,0);
76     while (K--){
77         scanf("%d%d", &u, &v);
78         printf("%d\n", lca_max(u,v));
79     }
80     return 0;
81 }

 

posted @ 2016-05-26 15:39  mzl0707  阅读(150)  评论(0)    收藏  举报