BZOJ 4016 最短路径树问题 最短路径树构造+点分治
题目:
分析:
大家都说这是一道强行拼出来的题,属于是两种算法的模板题。
我们用dijkstra算法算出1为源点的最短路数组,然后遍历一下建出最短路树。
之后就是裸的点分治算法,一个桶,两个变量就解决了这道题。
代码:
1 #include<bits/stdc++.h> 2 #define pi pair<int,int> 3 #define pq priority_queue 4 #define mp(a,b) make_pair(a,b) 5 #define ms(a,x) memset(a,x,sizeof(a)) 6 using namespace std; 7 const int N=30005; 8 vector< pi >g[N]; 9 struct node{int y,z,nxt;}e[N*4]; 10 int n,m,k,h[N],c=0,dis[N],vis[N],nm[N]; 11 int ans2,md,rt,sm,siz[N],s[N],ans,f[N]; 12 pq< pi,vector< pi >,greater< pi > >q; 13 void add(int x,int y,int z){ 14 e[++c]=(node){y,z,h[x]};h[x]=c; 15 e[++c]=(node){x,z,h[y]};h[y]=c; 16 } void dij(){ 17 ms(vis,0);ms(dis,0x3f); 18 dis[1]=0;q.push(mp(0,1)); 19 while(!q.empty()){ 20 int x=q.top().second;q.pop(); 21 if(vis[x]) continue;vis[x]=1; 22 for(int i=0;i<g[x].size();i++){ 23 int y=g[x][i].first, 24 d=g[x][i].second; 25 if(dis[y]>dis[x]+d) dis[y]=dis[x]+d, 26 q.push(mp(dis[y],y)); 27 } 28 } return ; 29 } void rebuild(int x){ 30 vis[x]=1; 31 for(int i=0;i<g[x].size();i++){ 32 int y=g[x][i].first,d=g[x][i].second; 33 if(vis[y]||dis[x]+d!=dis[y]) continue; 34 add(x,y,d);rebuild(y); 35 } return ; 36 } void getrt(int x,int fa){ 37 siz[x]=1;f[x]=0; 38 for(int i=h[x],y;i;i=e[i].nxt) 39 if(!vis[y=e[i].y]&&y!=fa) getrt(y,x), 40 siz[x]+=siz[y],f[x]=max(f[x],siz[y]); 41 f[x]=max(f[x],sm-siz[x]); 42 if(f[rt]>f[x]) rt=x;return ; 43 } void dfs(int x,int fa,int nw){ 44 md=max(md,nw); 45 if(nw==k-1){ 46 if(ans==dis[x]) ans2++; 47 if(dis[x]>ans) ans2=1, 48 ans=dis[x];return ; 49 } int nans=-1; 50 if(s[k-1-nw]!=-1) nans=dis[x]+s[k-1-nw]; 51 if(ans==nans) ans2+=nm[k-1-nw]; 52 if(nans>ans) ans2=nm[k-1-nw],ans=nans; 53 for(int i=h[x],y;i;i=e[i].nxt) 54 if(!vis[y=e[i].y]&&y!=fa) 55 dis[y]=dis[x]+e[i].z,dfs(y,x,nw+1); 56 } void update(int x,int fa,int nw){ 57 if(nw==k-1) return ; 58 if(s[nw]==dis[x]) nm[nw]++; 59 else s[nw]=max(s[nw],dis[x]),nm[nw]=1; 60 for(int i=h[x],y;i;i=e[i].nxt) 61 if(!vis[y=e[i].y]&&y!=fa) update(y,x,nw+1); 62 } void solve(int x){ 63 md=0;vis[x]=1; 64 for(int i=h[x],y;i;i=e[i].nxt) 65 if(!vis[y=e[i].y]) dis[y]=e[i].z, 66 dfs(y,x,1),update(y,x,1); 67 for(int i=1;i<=md;i++) s[i]=-1,nm[i]=0; 68 for(int i=h[x],y;i;i=e[i].nxt) 69 if(!vis[y=e[i].y]) sm=siz[y],rt=0, 70 getrt(y,x),solve(rt); 71 } int main(){ 72 f[0]=0x3f3f3f3f;scanf("%d%d%d",&n,&m,&k); 73 for(int i=1,x,y,z;i<=m;i++){ 74 scanf("%d%d%d",&x,&y,&z); 75 g[x].push_back(mp(y,z)); 76 g[y].push_back(mp(x,z)); 77 } for(int i=1;i<=n;i++) 78 sort(g[i].begin(),g[i].end()); 79 dij();ms(vis,0);rebuild(1); 80 sm=n;rt=0;ms(vis,0); 81 ms(dis,0);ms(s,-1); 82 getrt(1,0);solve(rt); 83 printf("%d %d\n",ans,ans2); 84 return 0; 85 }