zoukankan      html  css  js  c++  java
  • HDU4871 Shortest-path tree(最短路径树 + 树的点分治)

    题目大概要先求一张边有权的图的根为1的最短路径树,要满足根到各点路径序列的字典序最小;然后求这棵最短路径树包含k个结点的最长路径的长度和个数。

    首先先构造出这棵字典序最小的最短路径树。。好吧,我太傻逼了,不会。。保证邻接表存储邻接点有序的前提下,就能按字典序DFS一遍,在O(N+E)的时间复杂度上构造出来了。

    然后就是统计路径最长长度和方案数,树上路径问题当然就是树分治了。

    不多谈。。%¥……¥%……¥……连续写了200多行然后一直出数据调了2个多小时才AC。。

      1 #include<cstdio>
      2 #include<cstring>
      3 #include<queue>
      4 #include<algorithm>
      5 using namespace std;
      6 #define INF (1<<30)
      7 #define MAXN 33333
      8 #define MAXM 66666*2
      9 
     10 struct Edge{
     11     int v,w,next;
     12 }edge[MAXM];
     13 int NE,head[MAXN];
     14 void addEdge(int u,int v,int w){
     15     edge[NE].v=v; edge[NE].w=w;
     16     edge[NE].next=head[u]; head[u]=NE++;
     17 }
     18 
     19 int d[MAXN];
     20 bool vis[MAXN];
     21 void SPFA(int n){
     22     for(int i=1; i<=n; ++i){
     23         d[i]=INF; vis[i]=0;
     24     }
     25     d[1]=0; vis[1]=1;
     26     queue<int> que;
     27     que.push(1);
     28     while(!que.empty()){
     29         int u=que.front(); que.pop();
     30         for(int i=head[u]; i!=-1; i=edge[i].next){
     31             int v=edge[i].v;
     32             if(d[v]>d[u]+edge[i].w){
     33                 d[v]=d[u]+edge[i].w;
     34                 if(!vis[v]){
     35                     vis[v]=1;
     36                     que.push(v);
     37                 }
     38             }
     39         }
     40         vis[u]=0;
     41     }
     42 }
     43 
     44 struct Node{
     45     int u,v,w;
     46     bool operator<(const Node &nd)const{
     47         if(u==nd.u) return nd.v<v;
     48         return u<nd.u;
     49     }
     50 }node[MAXM];
     51 int cnt;
     52 
     53 void dfs(int u){
     54     vis[u]=1;
     55     for(int i=head[u]; i!=-1; i=edge[i].next){
     56         int v=edge[i].v;
     57         if(vis[v] || d[u]+edge[i].w!=d[v]) continue;
     58         node[cnt].u=u; node[cnt].v=v; node[cnt].w=edge[i].w;
     59         ++cnt;
     60         dfs(v);
     61     }
     62 }
     63 
     64 int size[MAXN];
     65 void getsize(int u,int fa){
     66     size[u]=1;
     67     for(int i=head[u]; i!=-1; i=edge[i].next){
     68         int v=edge[i].v;
     69         if(vis[v] || v==fa) continue;
     70         getsize(v,u);
     71         size[u]+=size[v];
     72     }
     73 }
     74 int mini,cen;
     75 void getcen(int u,int fa,int &tot){
     76     int res=tot-size[u];
     77     for(int i=head[u]; i!=-1; i=edge[i].next){
     78         int v=edge[i].v;
     79         if(vis[v] || v==fa) continue;
     80         res=max(res,size[v]);
     81         getcen(v,u,tot);
     82     }
     83     if(res<mini){
     84         mini=res;
     85         cen=u;
     86     }
     87 }
     88 int getcen(int u){
     89     getsize(u,u);
     90     mini=INF;
     91     getcen(u,u,size[u]);
     92     return cen;
     93 }
     94 
     95 int k;
     96 int a_val[MAXN],a_cnt[MAXN],a_rec[MAXN],an,b_val[MAXN],b_cnt[MAXN],b_rec[MAXN],bn;
     97 bool tag[MAXN];
     98 int ans_val,ans_cnt;
     99 void conqur_dfs(int u,int fa,int val,int tot){
    100     if(b_val[tot]<val){
    101         b_val[tot]=val;
    102         b_cnt[tot]=1;
    103         if(!tag[tot]){
    104             tag[tot]=1;
    105             b_rec[bn++]=tot;
    106         }
    107     }else if(b_val[tot]==val){
    108         ++b_cnt[tot];
    109     }
    110     for(int i=head[u]; i!=-1; i=edge[i].next){
    111         int v=edge[i].v;
    112         if(vis[v] || v==fa) continue;
    113         conqur_dfs(v,u,val+edge[i].w,tot+1);
    114     }
    115 }
    116 void conqur(int u){
    117     an=0;
    118     for(int i=head[u]; i!=-1; i=edge[i].next){
    119         int v=edge[i].v;
    120         if(vis[v]) continue;
    121         bn=0;
    122         conqur_dfs(v,v,edge[i].w,1);
    123         for(int j=0; j<bn; ++j){
    124             if(b_rec[j]==k-1){
    125                 if(b_val[b_rec[j]]>ans_val){
    126                     ans_val=b_val[b_rec[j]];
    127                     ans_cnt=b_cnt[b_rec[j]];
    128                 }else if(b_val[b_rec[j]]==ans_val){
    129                     ans_cnt+=b_cnt[b_rec[j]];
    130                 }
    131             }else if(b_rec[j]<k-1){
    132                 int tmp=k-1-b_rec[j];
    133                 if(a_cnt[tmp]==0) continue;
    134                 if(b_val[b_rec[j]]+a_val[tmp]>ans_val){
    135                     ans_val=b_val[b_rec[j]]+a_val[tmp];
    136                     ans_cnt=b_cnt[b_rec[j]]*a_cnt[tmp];
    137                 }else if(b_val[b_rec[j]]+a_val[tmp]==ans_val){
    138                     ans_cnt+=b_cnt[b_rec[j]]*a_cnt[tmp];
    139                 }
    140             }
    141         }
    142         for(int j=0; j<bn; ++j){
    143             int tmp=b_rec[j];
    144             tag[tmp]=0;
    145             a_rec[an++]=tmp;
    146             if(a_val[tmp]<b_val[tmp]){
    147                 a_val[tmp]=b_val[tmp];
    148                 a_cnt[tmp]=b_cnt[tmp];
    149             }else if(a_val[tmp]==b_val[tmp]){
    150                 a_cnt[tmp]+=b_cnt[tmp];
    151             }
    152             b_val[tmp]=0;
    153             b_cnt[tmp]=0;
    154         }
    155     }
    156     for(int i=0; i<an; ++i){
    157         a_val[a_rec[i]]=0;
    158         a_cnt[a_rec[i]]=0;
    159     }
    160 }
    161 
    162 void divide(int u){
    163     u=getcen(u);
    164     vis[u]=1;
    165     conqur(u);
    166     for(int i=head[u]; i!=-1; i=edge[i].next){
    167         int v=edge[i].v;
    168         if(vis[v]) continue;
    169         divide(v);
    170     }
    171 }
    172 
    173 int main(){
    174     int t,n,m,a,b,c;
    175     scanf("%d",&t);
    176     while(t--){
    177         NE=0;
    178         memset(head,-1,sizeof(head));
    179         scanf("%d%d%d",&n,&m,&k);
    180         for(int i=0; i<m; ++i){
    181             scanf("%d%d%d",&a,&b,&c);
    182             node[i<<1].u=a; node[i<<1].v=b; node[i<<1].w=c;
    183             node[i<<1|1].u=b; node[i<<1|1].v=a; node[i<<1|1].w=c;
    184         }
    185         sort(node,node+(m<<1));
    186         for(int i=0; i<(m<<1); ++i){
    187             addEdge(node[i].u,node[i].v,node[i].w);
    188         }
    189         SPFA(n);
    190         cnt=0;
    191         memset(vis,0,sizeof(vis));
    192         dfs(1);
    193         NE=0;
    194         memset(head,-1,sizeof(head));
    195         for(int i=0; i<cnt; ++i){
    196             addEdge(node[i].u,node[i].v,node[i].w);
    197             addEdge(node[i].v,node[i].u,node[i].w);
    198         }
    199         memset(vis,0,sizeof(vis));
    200         ans_val=0; ans_cnt=0;
    201         divide(1);
    202         printf("%d %d
    ",ans_val,ans_cnt);
    203     }
    204     return 0;
    205 }
  • 相关阅读:
    经典傻逼题
    谈谈Spring的IoC之注解扫描
    吴裕雄 python 神经网络——TensorFlow 花瓣分类与迁移学习(1)
    吴裕雄 python 神经网络——TensorFlow 实现LeNet-5模型处理MNIST手写数据集
    吴裕雄 python 神经网络——TensorFlow 花瓣识别2
    吴裕雄 python 神经网络——TensorFlow训练神经网络:花瓣识别
    吴裕雄 python 神经网络——TensorFlow训练神经网络:卷积层、池化层样例
    吴裕雄 python 神经网络——TensorFlow训练神经网络:MNIST最佳实践
    吴裕雄 python 神经网络——TensorFlow训练神经网络:不使用滑动平均
    吴裕雄 python 神经网络——TensorFlow训练神经网络:不使用隐藏层
  • 原文地址:https://www.cnblogs.com/WABoss/p/5476971.html
Copyright © 2011-2022 走看看