【BZOJ3732】 Network Kruskal+倍增lca

Description

给你N个点的无向图 (1 <= N <= 15,000),记为:1…N。 
图中有M条边 (1 <= M <= 30,000) ,第j条边的长度为: d_j ( 1 < = d_j < = 1,000,000,000).

现在有 K个询问 (1 < = K < = 15,000)。 
每个询问的格式是:A B,表示询问从A点走到B点的所有路径中,最长的边最小值是多少?

Input

第一行: N, M, K。 
第2..M+1行: 三个正整数:X, Y, and D (1 <= X <=N; 1 <= Y <= N). 表示X与Y之间有一条长度为D的边。 
第M+2..M+K+1行: 每行两个整数A B,表示询问从A点走到B点的所有路径中,最长的边最小值是多少?

Output

 对每个询问,输出最长的边最小值是多少。

Sample Input

6 6 8
1 2 5
2 3 4
3 4 3
1 4 8
2 5 7
4 6 2
1 2
1 3
1 4
2 3
2 4
5 1
6 2
6 1

Sample Output

5
5
5
4
4
7
4
5

HINT

 

1 <= N <= 15,000 

1 <= M <= 30,000 

1 <= d_j <= 1,000,000,000 

1 <= K <= 15,000 

 

Source

 

找到一个最小生成树,然后lca就好。。。肉眼查错大法好。。
 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <algorithm>
 5 #include <cmath>
 6 #define M 30010
 7 #define N 15010
 8 #define inf 0x7fffffff
 9 using namespace std;
10 struct node1{int x,y,v;}d[M]; 
11 struct node2{int next,v,to;}e[M];
12 int n,m,k,cnt;
13 int fa[N][20],fa_max[N][20],belong[N],dpt[N],head[N];
14 inline int read() {char c; int ans=0; while ((c=getchar())==' ' || c=='\n' || c=='\r'); ans=c-'0'; while (isdigit(c=getchar())) ans=ans*10+c-'0'; return ans;}
15 bool cmp(node1 a,node1 b){return a.v<b.v;}
16 void adde(int x,int y,int z) {cnt++; e[cnt].next=head[x]; head[x]=cnt; e[cnt].to=y; e[cnt].v=z;}
17 int findfa(int x)
18 {
19     if (!belong[x] || belong[x]==x) return belong[x]=x;
20     else return belong[x]=findfa(belong[x]);
21 }
22 void bfework(int x)
23 {
24     dpt[x]=dpt[fa[x][0]]+1;
25     for (int i=head[x];i;i=e[i].next)
26     {
27         if (e[i].to==fa[x][0]) continue;
28         fa[e[i].to][0]=x;
29         fa_max[e[i].to][0]=e[i].v;
30         bfework(e[i].to);
31     }
32 }
33 int query(int x,int y)
34 {
35     int ans=-inf;
36     if (dpt[x]<dpt[y]) swap(x,y);
37     for (int i=14;~i;i--)
38         if (dpt[fa[x][i]]>=dpt[y]) 
39             ans=max(ans,fa_max[x][i]),x=fa[x][i];
40     if (x==y) return ans;
41     for (int i=14;~i;i--)
42         if (fa[x][i]!=fa[y][i])
43         {
44             ans=max(max(fa_max[x][i],fa_max[y][i]),ans);
45             x=fa[x][i];
46             y=fa[y][i];
47         }
48     ans=max(max(fa_max[x][0],fa_max[y][0]),ans);
49     return ans;
50 }
51 int main()
52 {
53     n=read(); m=read(); k=read();
54     for (int i=1;i<=m;i++) {d[i].x=read(); d[i].y=read(); d[i].v=read();}
55     sort(d+1,d+m+1,cmp);
56     for (int i=1;i<=m;i++)
57     {
58         int fax=findfa(d[i].x),fay=findfa(d[i].y);
59         if (fax!=fay)
60         {
61             belong[fax]=fay;
62             adde(d[i].x,d[i].y,d[i].v);
63             adde(d[i].y,d[i].x,d[i].v);
64         }
65     }
66     bfework(1);
67     for (int i=1;i<=14;i++)
68         for (int j=1;j<=n;j++)
69             fa[j][i]=fa[fa[j][i-1]][i-1],fa_max[j][i]=max(fa_max[j][i-1],fa_max[fa[j][i-1]][i-1]);
70     for (int i=1;i<=k;i++)
71     {
72         int x,y;
73         x=read(); y=read();
74         printf("%d\n",query(x,y));
75     }
76 //    for (int i=1;i<=n;i++) printf("%d ",dpt[i]);
77 //    printf("%d ",fa_max[5][1]);
78     return 0;
79 }
View Code

 

—Anime Otaku Save The World.
posted @ 2016-03-20 17:53  DMoon  阅读(144)  评论(0编辑  收藏  举报