[BZOJ3732]Network

题目大意:
  一个$n(n\le15000)$个点,$m(m\le30000)$条边的无向图,每条边有一个边权$w_i$,$q(q\le20000)$次询问,每次询问点$(u,v)$所有路径中权值最大的边最小值是多少。

思路:
  LCA模板题,这里考虑使用Kruskal重构树。对于排完序的边新建一个虚点,权值为边权,作为两个顶点子树的父结点。询问时相当于询问重构树上两点LCA点权。

 1 #include<cstdio>
 2 #include<cctype>
 3 #include<cstring>
 4 #include<algorithm>
 5 inline int getint() {
 6     register char ch;
 7     while(!isdigit(ch=getchar()));
 8     register int x=ch^'0';
 9     while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0');
10     return x;
11 }
12 const int N=3e4,logN=15,M=6e4,M2=3e4;
13 struct Edge {
14     int to,next;
15 };
16 Edge e[M];
17 int h[N],sz,tot,n,m,q,val[N],dep[N],anc[N][logN];
18 inline void add_edge(const int &u,const int &v) {
19     e[sz]=(Edge){v,h[u]};h[u]=sz++;
20 }
21 struct Edge2 {
22     int u,v,w;
23     bool operator < (const Edge2 &another) const {
24         return w<another.w;
25     }
26 };
27 Edge2 e2[M2];
28 struct DisjointSet {
29     int anc[N];
30     DisjointSet() {
31         for(register int i=0;i<N;i++) anc[i]=i;
32     }
33     int find(const int &x) {
34         return x==anc[x]?x:anc[x]=find(anc[x]);
35     }
36     void merge(const int &x,const int &y) {
37         anc[find(x)]=find(y);
38     }
39     bool same(const int &x,const int &y) {
40         return find(x)==find(y);
41     }
42 };
43 DisjointSet s;
44 inline void kruskal() {
45     std::sort(&e2[0],&e2[m]);
46     for(register int i=0;i<m;i++) {
47         const int u=e2[i].u,v=e2[i].v,w=e2[i].w;
48         if(!s.same(u,v)) {
49             val[++tot]=w;
50             add_edge(tot,s.find(u));
51             add_edge(tot,s.find(v));
52             s.merge(u,tot);
53             s.merge(v,tot);
54         }
55     }
56 }
57 inline int log2(const float &x) {
58     return ((unsigned&)x>>23&255)-127;
59 }
60 void dfs(const int &x,const int &par) {
61     dep[x]=dep[anc[x][0]=par]+1;
62     for(register int i=1;i<=log2(dep[x]);i++) {
63         anc[x][i]=anc[anc[x][i-1]][i-1];
64     }
65     for(register int i=h[x];~i;i=e[i].next) {
66         const int &y=e[i].to;
67         dfs(y,x);
68     }
69 }
70 inline int lca(int x,int y) {
71     if(dep[x]!=dep[y]) {
72         if(dep[x]<dep[y]) std::swap(x,y);
73         for(register int i=log2(dep[x]-dep[y]);~i;i--) {
74             if(dep[anc[x][i]]>=dep[y]) x=anc[x][i];
75         }
76     }
77     if(x==y) return x;
78     for(register int i=log2(dep[x]);~i;i--) {
79         if(anc[x][i]!=anc[y][i]) {
80             x=anc[x][i];
81             y=anc[y][i];
82         }
83     }
84     return anc[x][0];
85 }
86 int main() {
87     memset(h,-1,sizeof h);
88     n=tot=getint(),m=getint(),q=getint();
89     for(register int i=0;i<m;i++) {
90         const int u=getint(),v=getint(),w=getint();
91         e2[i]=(Edge2){u,v,w};
92     }
93     kruskal();
94     dfs(tot,0);
95     for(register int i=0;i<q;i++) {
96         printf("%d\n",val[lca(getint(),getint())]);
97     }
98     return 0;
99 }

 

posted @ 2018-04-02 19:55  skylee03  阅读(89)  评论(0编辑  收藏  举报