BZOJ 4016 [FJOI2014]最短路径树问题

Posted Troy Ricardo

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了BZOJ 4016 [FJOI2014]最短路径树问题相关的知识,希望对你有一定的参考价值。

题目链接:

  TP

题解:

   我就是个智障。明明是道大水题,硬是拖了6h。

  关于这道题我唯一想说的就是,记得更新拆分后的子树大小!!!我就是ZZ恒(QwQ。

代码:

  

  1 #define Troy 10/26/2017
  2 
  3 #include <bits/stdc++.h>
  4 
  5 using namespace std;
  6 
  7 inline int read(){
  8     int s=0,k=1;char ch=getchar();
  9     while(ch<0|ch>9)    ch==-?k=-1:0,ch=getchar();
 10     while(ch>47&ch<=9)    s=s*10+(ch^48),ch=getchar();
 11     return s*k;
 12 }
 13 
 14 const int N=3e5+5;
 15 
 16 int n,m,K;
 17 
 18 struct edges{
 19     int v,w;edges *last;
 20 }edge[N<<1],*head[N];int cnt;
 21 
 22 inline void push(int u,int v,int w){
 23     edge[++cnt]=(edges){v,w,head[u]};head[u]=edge+cnt;
 24 }
 25 
 26 int q[N],dis[N],from[N];
 27 bool vis[N];
 28 
 29 inline void dfs(int x){
 30     vis[x]=true;
 31     vector<int > G; 
 32     for(edges *i=head[x];i;i=i->last)   if(!vis[i->v]&&dis[i->v]==dis[x]+i->w)
 33         G.push_back(i->v);
 34     sort(G.begin(),G.end());
 35     for(int i=0;i<G.size();i++){
 36         if(vis[G[i]])   continue;
 37         dfs(G[i]);
 38         from[G[i]]=x;
 39     }
 40 }
 41 
 42 inline void spfa(){
 43     int l=0,r=1;
 44     q[0]=1;
 45     memset(dis,127,sizeof(dis));
 46     dis[1]=0;
 47     while(l!=r){
 48         int x=q[l++];if(l==N)   l=0;
 49         for(edges *i=head[x];i;i=i->last){
 50             if(dis[x]+i->w<dis[i->v]){
 51                 dis[i->v]=dis[x]+i->w;
 52                 if(!vis[i->v])
 53                     vis[i->v]=true,q[r++]=i->v;
 54                 if(r==N)    r=0;
 55             }
 56         } 
 57         vis[x]=false;
 58     }
 59     dfs(1);
 60 }
 61 
 62 int heavy[N],root,size[N],tot,top,ans=0,sum,T[N],t[N],clocks,cnts[N];
 63 
 64 inline void dfs(int x,int fa){
 65     size[x]=1,heavy[x]=0;
 66     for(edges *i=head[x];i;i=i->last)if(i->v!=fa&&(!vis[i->v])){
 67         dfs(i->v,x);
 68         size[x]+=size[i->v];
 69         heavy[x]=max(heavy[x],size[i->v]);
 70     }
 71     heavy[x]=max(heavy[x],tot-size[x]);
 72     if(heavy[x]<=top)
 73         top=heavy[x],root=x;
 74 }
 75 
 76 struct node{
 77     int v,w;
 78     inline friend bool operator <(node x,node y){
 79         return size[x.v]<size[y.v];
 80     }
 81 }sons[N];
 82 
 83 inline void calc(int x,int fa,int w,int deep){
 84     if(T[K-deep]==clocks){
 85         if(ans<t[K-deep]+w)
 86             ans=t[K-deep]+w,sum=0;
 87         if(ans==t[K-deep]+w)
 88             sum+=cnts[K-deep];
 89     }
 90     if(deep+1<K)
 91         for(edges *i=head[x];i;i=i->last)   if(i->v!=fa&&vis[i->v]==0){
 92             calc(i->v,x,w+i->w,deep+1);
 93         }
 94 }
 95 
 96 inline void update(int x,int fa,int w,int deep){
 97     if(T[deep]==clocks){
 98         if(t[deep]<w)
 99             t[deep]=w,cnts[deep]=0;
100         if(t[deep]==w)
101             cnts[deep]++;
102     }
103     else    T[deep]=clocks,t[deep]=w,cnts[deep]=1;
104     if(deep<K)
105         for(edges *i=head[x];i;i=i->last)   if(i->v!=fa&&vis[i->v]==0){
106             update(i->v,x,w+i->w,deep+1);
107         }
108 }
109 
110 inline void solve(int x){
111     clocks++;
112     top=0x7fffffff;
113     dfs(x,x);       
114     vis[root]=true;
115     x=root;
116     int num(0);
117     T[1]=clocks;
118     for(edges *i=head[x];i;i=i->last)if(vis[i->v]^1){
119         sons[++num]=(node){i->v,i->w};
120     }
121     sort(sons+1,sons+1+num);
122     for(int i=1;i<=num;i++){
123         calc(sons[i].v,x,sons[i].w,1);
124         if(i<num)
125             update(sons[i].v,x,sons[i].w,2);
126     }       
127 
128     for(edges *i=head[x];i;i=i->last)    if(vis[i->v]^1)
129     if(size[i->v]>=K){
130         tot=size[i->v],solve(i->v);
131     }
132 
133 }
134 
135 int main(){
136     n=read(),m=read(),K=read();
137     for(int i=1,u,v,w;i<=m;i++){
138         u=read(),v=read(),w=read();
139         push(u,v,w);push(v,u,w);
140     }
141     spfa();
142     memset(vis,0,sizeof(vis));
143     memset(head,0,sizeof(head));
144     cnt=0;
145     for(int i=2;i<=n;i++)
146         push(from[i],i,dis[i]-dis[from[i]]),
147         push(i,from[i],dis[i]-dis[from[i]]);
148     tot=n;
149     cnts[1]=1;
150     solve(1);        
151     printf("%d %d\n",ans,sum);
152 }

 

以上是关于BZOJ 4016 [FJOI2014]最短路径树问题的主要内容,如果未能解决你的问题,请参考以下文章

BZOJ4016: [FJOI2014]最短路径树问题

BZOJ4016: [FJOI2014]最短路径树问题

BZOJ 4016: [FJOI2014]最短路径树问题( 最短路 + 点分治 )

[BZOJ4016][FJOI2014]最短路径树问题

[BZOJ4016][FJOI2014]最短路径树问题(dijkstra+点分治)

BZOJ_4016_[FJOI2014]最短路径树问题_最短路+点分治