[BZOJ]3732: Network

传送门

就是一道LCA的应用;

不过重点(个人观点,勿喷)在于

想到这条{最长的边最小值}的路径在MST(最小生成树)上;

想到这一点之后,基本就会了。

还有第二个小问题,怎么lca求路径最大值。

 

 

 

 

 



ANS:蛮simple的,只要在跳lca的时候记录最大值就可以了。

 


 

代码:

  1 #include<bits/stdc++.h>
  2 using namespace std;
  3 int n,m,p;
  4 struct pp
  5 {
  6     int to,nxt,val;
  7 }e[600005];
  8 struct p1
  9 {
 10     int x,y,z;
 11 }g[300005];
 12 bool cmp(p1 x,p1 y) {return x.z<y.z;}
 13 int head[300005];
 14 int tot;
 15 int v[300005][22];
 16 int dep[300005];
 17 void add(int x,int y,int z)
 18 {
 19     e[++tot].to=y;
 20     e[tot].val=z;
 21     e[tot].nxt=head[x];
 22     head[x]=tot;
 23 }
 24 int f[300005][22];
 25 void dfs(int x)
 26 {
 27     for(int i=head[x];i;i=e[i].nxt)
 28     {
 29         int y=e[i].to;
 30         if(y==f[x][0]) continue;
 31         dep[y]=dep[x]+1;
 32         f[y][0]=x;
 33         v[y][0]=e[i].val;
 34         dfs(y);
 35     }
 36 }
 37 int lca(int x,int y)
 38 {
 39     if(dep[x]<dep[y]) swap(x,y);
 40     int d=dep[x]-dep[y],res=0;
 41     for(int i=0,p=1;i<20;i++,p<<=1)
 42         if(d&p)
 43         {
 44             res=max(res,v[x][i]);
 45             x=f[x][i];
 46         }
 47     if(x==y) return res;
 48     for(int i=19;i>=0;i--)
 49     {
 50         if(f[x][i]==f[y][i]) continue;
 51         res=max(res,v[x][i]);
 52         res=max(res,v[y][i]);
 53         x=f[x][i];
 54         y=f[y][i];
 55     }
 56     return max(res,max(v[x][0],v[y][0]));
 57 }
 58 int fa[300005];
 59 int findf(int x) {return fa[fa[x]]==fa[x]? fa[x]:fa[x]=findf(fa[x]);}
 60 void krustal()
 61 {
 62     sort(g+1,g+m+1,cmp);
 63     for(int i=1;i<=n;i++)fa[i]=i;
 64     int cnt=1;
 65     for(int i=1;i<=m;i++)
 66     {
 67         int fx=findf(g[i].x),fy=findf(g[i].y);
 68         if(fx==fy)continue;
 69         fa[fx]=fy;
 70         add(g[i].x,g[i].y,g[i].z);
 71         add(g[i].y,g[i].x,g[i].z);
 72         if(++cnt==n) break;
 73     }
 74 }
 75 
 76 int main()
 77 {
 78     memset(head,-1,sizeof(head));
 79     tot=0;
 80     cin>>n>>m>>p;
 81     for(int i=1;i<=m;i++) scanf("%d%d%d",&g[i].x,&g[i].y,&g[i].z);
 82     krustal();
 83     
 84     dfs(1);
 85     for(int j=1;j<20;j++)
 86         for(int i=1;i<=n;i++)
 87         {
 88             f[i][j]=f[f[i][j-1]][j-1];
 89             v[i][j]=max(v[i][j-1],v[f[i][j-1]][j-1]);
 90         }
 91     int x,y;
 92     while(p--)
 93     {
 94         scanf("%d%d",&x,&y);
 95         printf("%d\n",lca(x,y));
 96     }
 97     return 0;
 98 }
 99 /*
100 6 6 8
101 1 2 5
102 2 3 4
103 3 4 3
104 1 4 8
105 2 5 7
106 4 6 2
107 1 2
108 1 3
109 1 4
110 2 3
111 2 4
112 5 1
113 6 2
114 6 1
115 */
View Code

 

posted @ 2019-09-15 18:33  3_soon  阅读(72)  评论(0编辑  收藏  举报