luogu P1967 货车运输 最大生成树 倍增LCA

  1 #include <cstdio>
  2 #include <cstring>
  3 #include <algorithm>
  4 #include <cmath>
  5 using namespace std;
  6 struct edg
  7 {
  8     int x,y,w;
  9     friend bool operator < (edg x,edg y)
 10     {
 11         return x.w > y.w;
 12     } 
 13 } vec[110000];
 14 const int inf = 999999999;
 15 int n,m,q,cnt,l;
 16 int head[20010],nxt[150000],to[150000],val[150000];
 17 int p[20010][32],fa[100000],size[100000];
 18 int minn[20010][32],deep[20010];
 19 bool vis[20010];
 20 void add(int x,int y,int w)
 21 {
 22     cnt++;
 23     nxt[cnt] = head[x];
 24     head[x] = cnt;
 25     to[cnt] = y;
 26     val[cnt] = w;
 27 }
 28 int getfa(int x)
 29 {
 30     if (fa[x] == x) 
 31         return x;
 32     return fa[x] = getfa(fa[x]);
 33 }
 34 void merge(int x,int y)
 35 {
 36     int s1 = getfa(x),s2 = getfa(y);
 37     if (s1 == s2) 
 38         return;
 39     if (size[s1] < size[s2])
 40     {
 41         fa[s1] = s2;
 42         size[s2] += size[s1];
 43     }else
 44     {
 45         fa[s2] = s1;
 46         size[s1] += size[s2];
 47     }
 48 }
 49 void dfs(int x)
 50 {
 51     vis[x] = true;
 52     for (int tp = head[x];tp;tp = nxt[tp])
 53     {
 54         if (vis[to[tp]]) 
 55             continue;
 56         deep[to[tp]] = deep[x] + 1;
 57         p[to[tp]][0] = x;
 58         minn[to[tp]][0] = val[tp];
 59         dfs(to[tp]);
 60     }
 61 }
 62 void init()
 63 {
 64     for (int i = 1;i <= n;i++)
 65         if (!vis[i]) 
 66         {
 67             p[i][0] = 0;
 68             deep[i] = 1;
 69             dfs(i);
 70         }
 71     l = log2(n);
 72     for (int i = 1;i <= l;i++)
 73         for (int j = 1;j <= n;j++)
 74         {
 75             p[j][i] = p[p[j][i - 1]][i - 1];
 76             minn[j][i] = min(minn[j][i - 1],minn[p[j][i - 1]][i - 1]);
 77         }
 78 }
 79 int lca(int a,int b)
 80 {
 81     int ans = inf;
 82     if (deep[a] < deep[b]) 
 83         swap(a,b);
 84     for (int j = l;j >= 0;j--)
 85         if (deep[p[a][j]] >= deep[b])
 86         {
 87             ans = min(ans,minn[a][j]);
 88             a = p[a][j];
 89             
 90         }
 91     if (a == b) 
 92         return ans;
 93     for (int j = l;j >= 0;j--)
 94     {
 95         if (p[a][j] != p[b][j]) 
 96         {
 97             ans = min(ans, min(minn[a][j], minn[b][j]));
 98             a = p[a][j];
 99             b = p[b][j];
100         }
101     }
102     if (p[a][0] != p[b][0] || p[a][0] == 0)
103         return -1; 
104     ans = min(ans,min(minn[a][0],minn[b][0]));
105     return ans;
106 }
107 int main()
108 {
109     scanf("%d%d",&n,&m);
110     for (int i = 1;i <= m;i++)
111         scanf("%d%d%d",&vec[i].x,&vec[i].y,&vec[i].w);
112     for (int i = 1;i <= n;i++)
113     {
114         fa[i] = i;
115         size[i] = 1;
116     }
117     sort(vec + 1,vec + m + 1);
118     for (int i = 1;i <= m;i++)
119         if (getfa(vec[i].x) != getfa(vec[i].y))
120         {
121             add(vec[i].x,vec[i].y,vec[i].w);
122             add(vec[i].y,vec[i].x,vec[i].w);
123             merge(vec[i].x,vec[i].y);
124         }
125     init();
126     scanf("%d",&q);
127     int ta,tb;
128     for (int i = 1;i <= q;i++)
129     {
130         scanf("%d%d",&ta,&tb);
131         printf("%d\n",lca(ta,tb));
132     }
133     return 0;
134 }

 

posted @ 2019-09-14 17:00  IAT14  阅读(138)  评论(0编辑  收藏  举报