# 【kruscal】【最小生成树】【块状树】bzoj3732 Network

  1 #include<cmath>
2 #include<cstdio>
3 #include<cstring>
4 #include<algorithm>
5 using namespace std;
6 #define maxn 15001
7 int Res,Num;char C,CH[20];
8 inline int Ge()
9 {
10     Res=0;C='*';
11     while(C<'0'||C>'9')C=getchar();
12     while(C>='0'&&C<='9'){Res=Res*10+(C-'0');C=getchar();}
13     return Res;
14 }
15 inline void P(int x)
16 {
17     Num=0;if(!x){putchar('0');puts("");return;}
18     while(x>0)CH[++Num]=x%10,x/=10;
19     while(Num)putchar(CH[Num--]+48);
20     putchar('\n');
21 }
23 bool cmp(const Edge &a,const Edge &b){return a.w<b.w;}
24 Edge edges[maxn<<1];
25 struct Graph
26 {
27     int v[maxn<<1],first[maxn<<1],next[maxn<<1],w[maxn<<1],en;
28     void AddEdge(const int &a,const int &b)
29     {v[++en]=b;next[en]=first[a];first[a]=en;}
30     void AddEdge(const int &a,const int &b,const int &c)
31     {v[++en]=b;w[en]=c;next[en]=first[a];first[a]=en;}
32 };
33 Graph G[2];
34 int fa[maxn],dep[maxn],top[maxn],siz[maxn],sz,maxv[maxn],W[maxn];
35 int n,m,q,x,y;
36 void makeblock(int cur)
37 {
38     for(int i=G[0].first[cur];i;i=G[0].next[i])
39       if(G[0].v[i]!=fa[cur])
40         {
41           dep[G[0].v[i]]=dep[cur]+1;
42           W[G[0].v[i]]=G[0].w[i];
43           fa[G[0].v[i]]=cur;
44           if(siz[top[cur]]<sz)
45             {
46               siz[top[cur]]++;
47               top[G[0].v[i]]=top[cur];
49             }
50           makeblock(G[0].v[i]);
51         }
52 }
53 int rank[maxn],father[maxn];
54 void init(){for(int i=1;i<=n;i++) father[i]=i;}
55 int findroot(int x)
56 {
57     if(father[x]==x) return x;
58     int rt=findroot(father[x]);
59     father[x]=rt;
60     return rt;
61 }
62 void Union(int U,int V)
63 {
64     if(rank[U]<rank[V]) father[U]=V;
65     else
66       {
67         father[V]=U;
68         if(rank[U]==rank[V]) rank[U]++;
69       }
70 }
71 void dfs(int cur,int Maxnow)
72 {
73     maxv[cur]=Maxnow;
74     for(int i=G[1].first[cur];i;i=G[1].next[i])
75       dfs(G[1].v[i],max(Maxnow,W[G[1].v[i]]));
76 }
77 int Query_max(int u,int v)
78 {
79     int res=-2147483647;
80     while(u!=v)
81       {
82           if(top[u]==top[v])
83             {
84                 if(dep[u]<dep[v]) swap(u,v);
85                 res=max(res,W[u]);
86                 u=fa[u];
87             }
88           else
89             {
90                 if(dep[top[u]]<dep[top[v]]) swap(u,v);
91                 res=max(res,maxv[u]);
92                 u=fa[top[u]];
93             }
94       }
95     return res;
96 }
97 int main()
98 {
99     n=Ge();m=Ge();q=Ge();
101     sort(edges+1,edges+m+1,cmp);
102     init();
103     int cnt=0;
104     for(int i=1;i<=m;i++)
105       {
106           int f1=findroot(edges[i].u),f2=findroot(edges[i].v);
107           if(f1!=f2)
108             {
109                 Union(f1,f2);
112                 cnt++;
113                 if(cnt==n-1) break;
114             }
115       }
116     sz=sqrt(n);
117     for(int i=1;i<=n;i++)
118       {
119           top[i]=i;
120           siz[i]=1;
121       }
122     makeblock(1);
123     for(int i=1;i<=n;i++) if(top[i]==i) dfs(i,W[i]);
124     for(int i=1;i<=q;i++) {x=Ge();y=Ge();P(Query_max(x,y));}
125     return 0;
126 }