【BZOJ 4016】 [FJOI2014]最短路径树问题
2017-10-28 17:08
387 查看
题目链接:
TP题解:
我就是个智障。明明是道大水题,硬是拖了6h。关于这道题我唯一想说的就是,记得更新拆分后的子树大小!!!我就是ZZ恒(QwQ。
代码:
#define Troy 10/26/2017 #include <bits/stdc++.h> using namespace std; inline int read(){ int s=0,k=1;char ch=getchar(); while(ch<'0'|ch>'9') ch=='-'?k=-1:0,ch=getchar(); while(ch>47&ch<='9') s=s*10+(ch^48),ch=getchar(); return s*k; } const int N=3e5+5; int n,m,K; struct edges{ int v,w;edges *last; }edge[N<<1],*head ;int cnt; inline void push(int u,int v,int w){ edge[++cnt]=(edges){v,w,head[u]};head[u]=edge+cnt; } int q ,dis ,from ; bool vis ; inline void dfs(int x){ vis[x]=true; vector<int > G; for(edges *i=head[x];i;i=i->last) if(!vis[i->v]&&dis[i->v]==dis[x]+i->w) G.push_back(i->v); sort(G.begin(),G.end()); for(int i=0;i<G.size();i++){ if(vis[G[i]]) continue; dfs(G[i]); from[G[i]]=x; } } inline void spfa(){ int l=0,r=1; q[0]=1; memset(dis,127,sizeof(dis)); dis[1]=0; while(l!=r){ int x=q[l++];if(l==N) l=0; for(edges *i=head[x];i;i=i->last){ if(dis[x]+i->w<dis[i->v]){ dis[i->v]=dis[x]+i->w; if(!vis[i->v]) vis[i->v]=true,q[r++]=i->v; if(r==N) r=0; } } vis[x]=false; } dfs(1); } int heavy ,root,size ,tot,top,ans=0,sum,T ,t ,clocks,cnts ; inline void dfs(int x,int fa){ size[x]=1,heavy[x]=0; for(edges *i=head[x];i;i=i->last)if(i->v!=fa&&(!vis[i->v])){ dfs(i->v,x); size[x]+=size[i->v]; heavy[x]=max(heavy[x],size[i->v]); } heavy[x]=max(heavy[x],tot-size[x]); if(heavy[x]<=top) top=heavy[x],root=x; } struct node{ int v,w; inline friend bool operator <(node x,node y){ return size[x.v]<size[y.v]; } }sons ; inline void calc(int x,int fa,int w,int deep){ if(T[K-deep]==clocks){ if(ans<t[K-deep]+w) ans=t[K-deep]+w,sum=0; if(ans==t[K-deep]+w) sum+=cnts[K-deep]; } if(deep+1<K) for(edges *i=head[x];i;i=i->last) if(i->v!=fa&&vis[i->v]==0){ calc(i->v,x,w+i->w,deep+1); } } inline void update(int x,int fa,int w,int deep){ if(T[deep]==clocks){ if(t[deep]<w) t[deep]=w,cnts[deep]=0; if(t[deep]==w) cnts[deep]++; } else T[deep]=clocks,t[deep]=w,cnts[deep]=1; if(deep<K) for(edges *i=head[x];i;i=i->last) if(i->v!=fa&&vis[i->v]==0){ update(i->v,x,w+i->w,deep+1); } } inline void solve(int x){ clocks++; top=0x7fffffff; dfs(x,x); vis[root]=true; x=root; int num(0); T[1]=clocks; for(edges *i=head[x];i;i=i->last)if(vis[i->v]^1){ sons[++num]=(node){i->v,i->w}; } sort(sons+1,sons+1+num); for(int i=1;i<=num;i++){ calc(sons[i].v,x,sons[i].w,1); if(i<num) update(sons[i].v,x,sons[i].w,2); } for(edges *i=head[x];i;i=i->last) if(vis[i->v]^1) if(size[i->v]>=K){ tot=size[i->v],solve(i->v); } } int main(){ n=read(),m=read(),K=read(); for(int i=1,u,v,w;i<=m;i++){ u=read(),v=read(),w=read(); push(u,v,w);push(v,u,w); } spfa(); memset(vis,0,sizeof(vis)); memset(head,0,sizeof(head)); cnt=0; for(int i=2;i<=n;i++) push(from[i],i,dis[i]-dis[from[i]]), push(i,from[i],dis[i]-dis[from[i]]); tot=n; cnts[1]=1; solve(1); printf("%d %d\n",ans,sum); }
相关文章推荐
- BZOJ 4016: [FJOI2014]最短路径树问题
- [bzoj 4016] [Fjoi 2014] 最短路径树问题
- BZOJ 4016: [FJOI2014]最短路径树问题( 最短路 + 点分治 )
- 【BZOJ 4016】[FJOI2014]最短路径树问题
- bzoj 4016 [FJOI2014]最短路径树问题(最短路径树+树分治)
- 【BZOJ4016】【FJOI2014】 最短路径树问题 树的点分治
- 【bzoj4016】[FJOI2014]最短路径树问题 堆优化Dijkstra+DFS树+树的点分治
- bzoj 4016: [FJOI2014]最短路径树问题 最短路+点分治
- 【BZOJ4016】[FJOI2014]最短路径树问题 最短路径树+点分治
- [BZOJ4016][FJOI2014]最短路径树问题(dijkstra+点分治)
- bzoj 4016: [FJOI2014]最短路径树问题
- 【bzoj4016】 FJOI2014—最短路径树问题
- BZOJ_4016_[FJOI2014]最短路径树问题_最短路+点分治
- 【BZOJ 4016】[FJOI2014]最短路径树问题
- bzoj 4016: [FJOI2014]最短路径树问题
- BZOJ 4016: [FJOI2014]最短路径树问题
- 4016: [FJOI2014]最短路径树问题
- 4016: [FJOI2014]最短路径树问题 点分治
- 4016: [FJOI2014]最短路径树问题
- [FJOI 2014]最短路径树问题