【洛谷P1967】[NOIP2013]貨車運輸

Claire_ljy發表於2020-04-04

貨車運輸

題目連結

 

顯然,從一點走到另一點的路徑中,最小值最大的路徑一定在它的最大生成樹上

所以要先求出最大生成樹,再在生成樹上找最近公共祖先,同時求出最小值。

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<algorithm>
  4 #include<vector>
  5 #include<cmath>
  6 using namespace std;
  7 
  8 const int MAXN = 10010 ;
  9 
 10 int n,m,fa[MAXN],f[MAXN][30],deep[MAXN],minn[MAXN][30];
 11 
 12 bool v[MAXN];
 13 
 14 struct Edge{
 15     int x;
 16     int y;
 17     int w;
 18 } e[50010];
 19 
 20 vector<int> son[MAXN],ww[MAXN];
 21 
 22 bool cmp(Edge x,Edge y)
 23 {
 24     return x.w>y.w;
 25 }
 26 
 27 int find(int x)
 28 {
 29     if(fa[x]!=x) fa[x]=find(fa[x]);
 30     return fa[x];
 31 }
 32 
 33 void init()
 34 {
 35     scanf("%d%d",&n,&m);
 36     for(int i=1;i<=n;i++)
 37      fa[i]=i;
 38     for(int i=1;i<=m;i++)
 39      scanf("%d%d%d",&e[i].x,&e[i].y,&e[i].w);
 40 }
 41 
 42 void unionn(int x,int y)
 43 {
 44     fa[find(x)]=find(y);
 45 }
 46 
 47 void mst()
 48 {
 49     sort(e+1,e+1+m,cmp);
 50     int t=0;
 51     for(int i=1;i<=m;i++)
 52     {
 53         int x=e[i].x,y=e[i].y;
 54         if(find(x)!=find(y))
 55         {
 56             unionn(x,y);
 57             t++;
 58             son[x].push_back(y);
 59             ww[x].push_back(e[i].w);
 60              son[y].push_back(x);
 61              ww[y].push_back(e[i].w);
 62              if(t==n-1) break;
 63          }
 64     }
 65 }
 66 
 67 void build(int now,int d)
 68 {
 69     v[now]=1;
 70     deep[now]=d;
 71     for(int i=1;(1<<i)<=deep[now];i++)
 72     {
 73         minn[now][i]=min(minn[now][i-1],minn[f[now][i-1]][i-1]);
 74         f[now][i]=f[f[now][i-1]][i-1];
 75     }
 76     for(int i=0;i<son[now].size();i++)
 77      if(!v[son[now][i]])
 78      {
 79          int u=son[now][i];
 80          minn[u][0]=ww[now][i];
 81          f[u][0]=now;
 82          build(u,d+1);
 83      }
 84 }
 85 
 86 int lca(int x,int y)
 87 {
 88     int ans=0x7fffffff;
 89     if(deep[x]!=deep[y])
 90     {
 91         if(deep[x]>deep[y]) swap(x,y);
 92         for(int i=20;i>=0;i--)
 93          if(deep[f[y][i]]>=deep[x])
 94          {
 95              ans=min(ans,minn[y][i]);
 96              y=f[y][i];
 97          }
 98     }
 99     if(x==y) return ans;
100     for(int i=20;i>=0;i--)
101      if(f[x][i]!=f[y][i])
102      {
103          ans=min(ans,minn[x][i]);
104          ans=min(ans,minn[y][i]);
105          x=f[x][i];
106          y=f[y][i];
107      }
108     ans=min(ans,minn[x][0]);
109     ans=min(ans,minn[y][0]);
110     if(ans==0x7fffffff||ans==0)
111     ans=-1;
112     return ans;
113 }
114 
115 void work()
116 {
117     int q;
118     scanf("%d",&q);
119     int x,y;
120     while(q--)
121     {
122         scanf("%d%d",&x,&y);
123         if(find(x)!=find(y))
124         printf("-1\n");
125         else
126         printf("%d\n",lca(x,y));
127     }
128 }
129 
130 int main()
131 {
132     init();
133     mst();
134     for(int i=1;i<=n;i++)
135     {
136         if(!v[i])
137         build(i,1);
138     }
139      work();
140     return 0;
141 }

 

轉載於:https://www.cnblogs.com/yjkhhh/p/8521369.html