zoukankan      html  css  js  c++  java
  • [loj2339]通道

    类似于[loj2553]

    对第一棵树边分治,对第二棵树建立虚树,并根据直径合并的性质来处理第三棵树(另外在第三棵树中计算距离需要使用dfs序+ST表做到$o(1)$优化)

    总复杂度为$o(nlog^{2}n)$,可以通过

      1 #include<bits/stdc++.h>
      2 using namespace std;
      3 #define N 100005
      4 #define ll long long
      5 #define pii pair<int,int>
      6 #define vi vector<int>
      7 #define fi first
      8 #define se second
      9 struct Edge{
     10     int nex,to;
     11     ll len; 
     12 };
     13 int n;
     14 ll ans,val[N];
     15 ll calc(vi x,vi y);
     16 ll dis3(int x,int y);
     17 namespace T1{
     18     int m,E,rt,x,y,head[N<<1],sz[N<<1],vis[N<<1];
     19     ll z,dep[N<<1];
     20     vi v,vx,vy;
     21     vector<pair<int,ll> >e[N<<1];
     22     Edge edge[N<<2];
     23     void add(int x,int y,ll z){
     24         edge[E]=Edge{head[x],y,z};
     25         head[x]=E++;
     26     }
     27     void dfs(int k,int fa,ll s){
     28         dep[k]=s;
     29         for(int i=head[k];i!=-1;i=edge[i].nex)
     30             if (edge[i].to!=fa)dfs(edge[i].to,k,s+edge[i].len);
     31         v.clear();
     32         for(int i=head[k];i!=-1;i=edge[i].nex)
     33             if (edge[i].to!=fa)v.push_back(edge[i].to);
     34         int lst=k;
     35         for(int i=0;i+2<v.size();i++){
     36             e[lst].push_back(make_pair(v[i],dep[v[i]]-dep[k]));
     37             e[lst].push_back(make_pair(++m,0));
     38             lst=m;
     39         }
     40         if (v.size()){
     41             e[lst].push_back(make_pair(v.back(),dep[v.back()]-dep[k]));
     42             v.pop_back();
     43             if (v.size())e[lst].push_back(make_pair(v.back(),dep[v.back()]-dep[k]));
     44         }
     45     }
     46     void build(){
     47         m=n;
     48         memset(head,-1,sizeof(head));
     49         for(int i=1;i<n;i++){
     50             scanf("%d%d%lld",&x,&y,&z);
     51             add(x,y,z),add(y,x,z);
     52         }
     53         dfs(1,0,0);
     54         E=0;
     55         memset(head,-1,sizeof(head));
     56         for(int i=1;i<=m;i++)assert(e[i].size()<=2); 
     57         for(int i=1;i<=m;i++)
     58             for(int j=0;j<e[i].size();j++){
     59                 add(i,e[i][j].fi,e[i][j].se);
     60                 add(e[i][j].fi,i,e[i][j].se);
     61             }
     62     }
     63     void get_sz(int k,int fa){
     64         sz[k]=1;
     65         for(int i=head[k];i!=-1;i=edge[i].nex)
     66             if ((!vis[i>>1])&&(edge[i].to!=fa)){
     67                 get_sz(edge[i].to,k);
     68                 sz[k]+=sz[edge[i].to];
     69             } 
     70     }
     71     void get_rt(int k,int fa,int s){
     72         for(int i=head[k];i!=-1;i=edge[i].nex)
     73             if ((!vis[i>>1])&&(edge[i].to!=fa)){
     74                 get_rt(edge[i].to,k,s);
     75                 if ((s<=3*sz[edge[i].to]+1)&&(3*sz[edge[i].to]<=(s+1<<1)))rt=(i>>1);
     76             }
     77     }
     78     void get_v(vi &v,int k,int fa,ll s){
     79         if (k<=n){
     80             val[k]=s;
     81             v.push_back(k);
     82         }
     83         for(int i=head[k];i!=-1;i=edge[i].nex)
     84             if ((!vis[i>>1])&&(edge[i].to!=fa))get_v(v,edge[i].to,k,s+edge[i].len);
     85     }
     86     void divide(int k){
     87         get_sz(k,0);
     88         if (sz[k]==1)return;
     89         get_rt(k,0,sz[k]);
     90         k=rt,vis[k]=1;
     91         vx.clear(),vy.clear();
     92         get_v(vx,edge[k<<1].to,0,0);
     93         get_v(vy,edge[(k<<1)|1].to,0,0);
     94         ans=max(ans,calc(vx,vy)+edge[k<<1].len);
     95         divide(edge[k<<1].to);
     96         divide(edge[(k<<1)|1].to);
     97     }
     98 };
     99 namespace T2{
    100     int E,x,y,head[N],dfn[N],sh[N],f[N][20],st[N];
    101     ll z,ans,dep[N];
    102     pii mx[N][2];
    103     vi v0,v,e[N];
    104     Edge edge[N<<1];
    105     bool cmp(int x,int y){
    106         return dfn[x]<dfn[y];
    107     }
    108     void add(int x,int y,ll z){
    109         edge[E]=Edge{head[x],y,z};
    110         head[x]=E++;
    111     }
    112     int lca(int x,int y){
    113         if (sh[x]<sh[y])swap(x,y);
    114         for(int i=19;i>=0;i--)
    115             if (sh[f[x][i]]>=sh[y])x=f[x][i];
    116         if (x==y)return x;
    117         for(int i=19;i>=0;i--)
    118             if (f[x][i]!=f[y][i])x=f[x][i],y=f[y][i];
    119         return f[x][0];
    120     }
    121     void dfs(int k,int fa,int s1,ll s2){
    122         dfn[k]=++dfn[0],sh[k]=s1,dep[k]=s2;
    123         f[k][0]=fa;
    124         for(int i=1;i<20;i++)f[k][i]=f[f[k][i-1]][i-1];
    125         for(int i=head[k];i!=-1;i=edge[i].nex)
    126             if (edge[i].to!=fa)dfs(edge[i].to,k,s1+1,s2+edge[i].len);
    127     }
    128     void build(){
    129         memset(head,-1,sizeof(head));
    130         for(int i=1;i<n;i++){
    131             scanf("%d%d%lld",&x,&y,&z);
    132             add(x,y,z),add(y,x,z);
    133         }
    134         dfs(1,1,0,0);
    135     }
    136     void build(vi v0){
    137         bool flag=0;
    138         for(int i=0;i<v0.size();i++)
    139             if (v0[i]==1)flag=1;
    140         if (!flag){
    141             v0.push_back(1);
    142             v.push_back(1);
    143         }
    144         sort(v0.begin(),v0.end(),cmp);
    145         st[0]=st[1]=1;
    146         for(int i=1;i<v0.size();i++){
    147             int k=lca(v0[i],st[st[0]]);
    148             while ((st[0]>1)&&(dfn[st[st[0]-1]]>=dfn[k])){
    149                 e[st[st[0]-1]].push_back(st[st[0]]);
    150                 st[0]--;
    151             }
    152             if (k!=st[st[0]]){
    153                 v.push_back(k);
    154                 e[k].push_back(st[st[0]]);
    155                 st[st[0]]=k;
    156             }
    157             st[++st[0]]=v0[i];
    158         }
    159         while (st[0]>1){
    160             e[st[st[0]-1]].push_back(st[st[0]]);
    161             st[0]--;
    162         }
    163     }
    164     ll merge_ans(pii x,pii y){
    165         return max(max(dis3(x.fi,y.fi),dis3(x.fi,y.se)),max(dis3(x.se,y.fi),dis3(x.se,y.se)));
    166     }
    167     pii merge(pii x,pii y){
    168         pii ans=x;
    169         if (dis3(y.fi,y.se)>dis3(ans.fi,ans.se))ans=y;
    170         if (dis3(x.fi,y.fi)>dis3(ans.fi,ans.se))ans=make_pair(x.fi,y.fi);
    171         if (dis3(x.fi,y.se)>dis3(ans.fi,ans.se))ans=make_pair(x.fi,y.se);
    172         if (dis3(x.se,y.fi)>dis3(ans.fi,ans.se))ans=make_pair(x.se,y.fi);
    173         if (dis3(x.se,y.se)>dis3(ans.fi,ans.se))ans=make_pair(x.se,y.se);
    174         return ans;
    175     }
    176     void dfs(int k){
    177         for(int i=0;i<e[k].size();i++){
    178             dfs(e[k][i]);
    179             ans=max(ans,merge_ans(mx[k][0],mx[e[k][i]][1])-(dep[k]<<1));
    180             ans=max(ans,merge_ans(mx[k][1],mx[e[k][i]][0])-(dep[k]<<1));
    181             mx[k][0]=merge(mx[k][0],mx[e[k][i]][0]);
    182             mx[k][1]=merge(mx[k][1],mx[e[k][i]][1]); 
    183         }
    184     }
    185     ll calc(vi vx,vi vy){
    186         ans=0,v0.clear();
    187         for(int i=0;i<vx.size();i++)v0.push_back(vx[i]);
    188         for(int i=0;i<vy.size();i++)v0.push_back(vy[i]);
    189         for(int i=0;i<v0.size();i++)val[v0[i]]+=dep[v0[i]];
    190         v=v0,build(v0);
    191         for(int i=0;i<v.size();i++)mx[v[i]][0]=mx[v[i]][1]=make_pair(-1,-1);
    192         for(int i=0;i<vx.size();i++)mx[vx[i]][0]=make_pair(vx[i],vx[i]);
    193         for(int i=0;i<vy.size();i++)mx[vy[i]][1]=make_pair(vy[i],vy[i]);
    194         dfs(1);
    195         for(int i=0;i<v.size();i++)e[v[i]].clear();
    196         return ans;
    197     }
    198 };
    199 namespace T3{
    200     int m,E,x,y,lg[N<<1],head[N],pos[N];
    201     ll z,ans,dep[N<<1],f[N<<1][20];
    202     Edge edge[N<<1];
    203     void add(int x,int y,ll z){
    204         edge[E]=Edge{head[x],y,z};
    205         head[x]=E++;
    206     }
    207     ll get_min(int x,int y){
    208         int m=lg[y-x+1];
    209         return min(f[x][m],f[y-(1<<m)+1][m]);
    210     }
    211     ll dis(int x,int y){
    212         x=pos[x],y=pos[y];
    213         if (x>y)swap(x,y);
    214         return dep[x]+dep[y]-(get_min(x,y)<<1);
    215     }
    216     void dfs(int k,int fa,ll s){
    217         dep[++m]=s,pos[k]=m;
    218         for(int i=head[k];i!=-1;i=edge[i].nex)
    219             if (edge[i].to!=fa){
    220                 dfs(edge[i].to,k,s+edge[i].len);
    221                 dep[++m]=s;
    222             }
    223     }
    224     void build(){
    225         memset(head,-1,sizeof(head));
    226         for(int i=1;i<n;i++){
    227             scanf("%d%d%lld",&x,&y,&z);
    228             add(x,y,z),add(y,x,z);
    229         }
    230         dfs(1,0,0);
    231         lg[0]=-1;
    232         for(int i=1;i<=m;i++)lg[i]=lg[i>>1]+1;
    233         for(int i=m;i;i--){
    234             f[i][0]=dep[i];
    235             for(int j=1;j<20;j++)f[i][j]=min(f[i][j-1],f[min(i+(1<<j-1),m)][j-1]);
    236         }
    237     }
    238 };
    239 ll calc(vi vx,vi vy){
    240     return T2::calc(vx,vy);
    241 }
    242 ll dis3(int x,int y){
    243     if ((x<0)||(y<0))return -1e18;
    244     return val[x]+val[y]+T3::dis(x,y); 
    245 }
    246 int main(){
    247     scanf("%d",&n);
    248     T1::build();
    249     T2::build();
    250     T3::build();
    251     T1::divide(1);
    252     printf("%lld
    ",ans);
    253     return 0;
    254 }
    View Code
  • 相关阅读:
    Spring核心思想:IOC(控制反转)、DI(依赖注入)和AOP(面向切面编程)
    synchronized 与 lock锁的异同
    SpringMVC工作流程
    close()和flush()的区别
    MySQL—索引(Index)
    MySQL—事务(ACID)
    MySQL—存储引擎
    周学习笔记(16)——大三下
    周学习笔记(15)——大三下
    周学习笔记(14)——大三下
  • 原文地址:https://www.cnblogs.com/PYWBKTDA/p/15316711.html
Copyright © 2011-2022 走看看