zoukankan      html  css  js  c++  java
  • BZOJ 4016 最短路径树问题 最短路径树构造+点分治

    题目:

      BZOJ4016最短路径树问题

    分析:

      大家都说这是一道强行拼出来的题,属于是两种算法的模板题。

      我们用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
    ",ans,ans2);
    84     return 0;
    85 }
    最短路树+点分治
  • 相关阅读:
    vertical blank interrupt 和 horizontal blank interrupt解释
    X server和windows manager的关系
    Kconfig中的select和depends on
    Debugging the kernel using Ftrace part 3
    Kernel: printk's no_console_suspend
    sql分割函数|在网上找的看着挺好,谁的忘了
    Ajax处理函数模板
    新闻添加html页面
    页码控件源码|分页页码控件源码
    谷歌本地商户中心 |谷歌本地商户中心 介绍|谷歌本地商户中心 网址
  • 原文地址:https://www.cnblogs.com/Alan-Luo/p/10446373.html
Copyright © 2011-2022 走看看