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


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

    Time Limit: 5 Sec  Memory Limit: 512 MB
    Submit: 1796  Solved: 625
    [Submit][Status][Discuss]

    Description

    给一个包含n个点,m条边的无向连通图。从顶点1出发,往其余所有点分别走一次并返回。
    往某一个点走时,选择总长度最短的路径走。若有多条长度最短的路径,则选择经过的顶点序列字典序最小的那条路径(如路径A为1,32,11,路 径B为1,3,2,11,路径B字典序较小。注意是序列的字典序的最小,而非路径中节点编号相连的字符串字典序最小)。到达该点后按原路返回,然后往其他 点走,直到所有点都走过。
    可以知道,经过的边会构成一棵最短路径树。请问,在这棵最短路径树上,最长的包含K个点的简单路径长度为多长?长度为该最长长度的不同路径有多少条?
    这里的简单路径是指:对于一个点最多只经过一次的路径。不同路径是指路径两端端点至少有一个不同,点A到点B的路径和点B到点A视为同一条路径。

    Input

    第一行输入三个正整数n,m,K,表示有 n个点m条边,要求的路径需要经过K个点。接下来输入m行,每行三个正整数Ai,Bi,Ci(1<=Ai,Bi<=n,1<=Ci& lt;=10000),表示Ai和Bi间有一条长度为Ci的边。数据保证输入的是连通的无向图。
     
     

    Output

    输出一行两个整数,以一个空格隔开,第一个整数表示包含K个点的路径最长为多长,第二个整数表示这样的不同的最长路径有多少条。
     

    Sample Input

    6 6 4
    1 2 1
    2 3 1
    3 4 1
    2 5 1
    3 6 1
    5 6 1

    Sample Output

    3 4

    HINT

    对于所有数据n<=30000,m<=60000,2<=K<=n。

    数据保证最短路径树上至少存在一条长度为K的路径。

    2016.12.7新加数据一组by - wyx-150137


    Source

    这题的题目已经告诉我们该怎么做了,先用dijkstra(或者spfa)找出最短路径图存在vector里,然后以字典序的优先原则dfs建出最短路径树,最后在树上点分治就好了。

    写的时候头是晕的,加上数组很多,错误百出。

    代码用时:2h

     1 #include<cstdio>
     2 #include<queue>
     3 #include<vector>
     4 #include<algorithm>
     5 #define rep(i,l,r) for (int i=l; i<=r; i++)
     6 #define For(i,x) for (int i=h[x],k; i; i=nxt[i])
     7 using namespace std;
     8 
     9 const int N=100100,inf=1000000000;
    10 int n,m,K,u,v,w,rt,sm,sum,mx,ans,num,vi[N],vv[N],dep[N],vis[N],d[N],s[N],sz[N],dis[N],sf[N],sg[N],f[N],g[N];
    11 struct P{ int x,v; };
    12 bool operator<(P a,P b){ return a.v>b.v; }
    13 priority_queue<P>Q;
    14 vector<int>V[N];
    15 
    16 struct E{
    17     int cnt,nxt[N<<1],to[N<<1],val[N<<1],h[N];
    18     void add(int u,int v,int w){ nxt[++cnt]=h[u]; to[cnt]=v; val[cnt]=w; h[u]=cnt; }
    19     void dijkstra(){
    20         rep(i,2,n) d[i]=inf; d[1]=0; Q.push((P){1,0});
    21         while (!Q.empty()){
    22             int x=Q.top().x; Q.pop();
    23             if (vi[x]) continue; vi[x]=1;
    24             For(i,x) if (d[k=to[i]]+val[i]==d[x]) V[k].push_back(i^1);
    25             For(i,x) if (d[k=to[i]]>d[x]+val[i]) d[k]=d[x]+val[i],Q.push((P){k,d[k]});
    26         }
    27     }
    28     
    29     void getroot(int x,int fa){
    30         sz[x]=1; s[x]=0;
    31         For(i,x) if (!vis[k=to[i]] && k!=fa) getroot(k,x),sz[x]+=sz[k],s[x]=max(s[x],sz[k]);
    32         s[x]=max(s[x],sum-sz[x]);
    33         if (s[x]<s[rt]) rt=x;
    34     }
    35     
    36     void getdeep(int x,int fa){
    37         For(i,x) if (!vis[k=to[i]] && k!=fa){
    38             dep[k]=dep[x]+1; dis[k]=dis[x]+val[i]; mx=max(mx,dep[k]);
    39             if (dis[k]>f[dep[k]]) f[dep[k]]=dis[k],sf[dep[k]]=1;
    40                 else if (dis[k]==f[dep[k]]) sf[dep[k]]++;
    41             getdeep(k,x);
    42         }
    43     }
    44     
    45     void que(int x){
    46         vis[x]=1; int sm=0;
    47         For(i,x) if (!vis[k=to[i]]){
    48             mx=dep[k]=1; dis[k]=f[1]=val[i]; sf[1]=1; getdeep(to[i],x);
    49             rep(j,1,min(mx,K)){
    50                 if (ans<f[j]+g[K-j]) ans=f[j]+g[K-j],num=sf[j]*sg[K-j];
    51                 else if (ans==f[j]+g[K-j]) num+=sf[j]*sg[K-j];
    52             }
    53             rep(j,1,min(mx,K)){
    54                 if (g[j]<f[j]) g[j]=f[j],sg[j]=sf[j];
    55                 else if (g[j]==f[j]) sg[j]+=sf[j];
    56             }
    57             rep(j,1,mx) f[j]=-inf,sf[j]=0;
    58             sm=max(sm,mx);
    59         }
    60         rep(i,1,min(sm,K)) g[i]=-inf,sg[i]=0;
    61         For(i,x) if (!vis[k=to[i]]) rt=0,sum=sz[k],getroot(k,x),que(rt);
    62     }
    63 }G,G1;
    64 bool cmp(int a,int b){ return G.to[a]<G.to[b]; }
    65 
    66 void dfs(int x){
    67     sort(V[x].begin(),V[x].end(),cmp);
    68     rep(i,0,(int)V[x].size()-1) if (!vv[G.to[V[x][i]]])
    69         vv[G.to[V[x][i]]]=1,G1.add(x,G.to[V[x][i]],G.val[V[x][i]]),G1.add(G.to[V[x][i]],x,G.val[V[x][i]]),dfs(G.to[V[x][i]]);
    70 }
    71 
    72 int main(){
    73     freopen("bzoj4016.in","r",stdin);
    74     freopen("bzoj4016.out","w",stdout);
    75     scanf("%d%d%d",&n,&m,&K); G.cnt=G1.cnt=1; K--;
    76     rep(i,1,m) scanf("%d%d%d",&u,&v,&w),G.add(u,v,w),G.add(v,u,w);
    77     G.dijkstra(); vv[1]=1 ; dfs(1);
    78     g[0]=0; sg[0]=1; s[0]=inf; sum=n; G1.getroot(1,0); G1.que(rt);
    79     printf("%d %d
    ",ans,num);
    80     return 0;
    81 }
  • 相关阅读:
    关于负数补码的求解
    二维数组的行列指针
    复杂类型的解读
    单斜杠''的思考
    HTML 文本格式化实例--常用的标签
    P1 基础知识以及客户截面 【B站 SolidWorks2014教学视频 共计20讲】
    SolidWorks 2-5 草图的绘制
    SolidWorks 2-4 草图简介
    SolidWorks 模型创建的一般过程 2019年2月25日
    P3 3.HTML&CSS基础_HTML简介 (24'22")---------- 高质量HTML与CSS基础(共103讲)
  • 原文地址:https://www.cnblogs.com/HocRiser/p/8421825.html
Copyright © 2020-2023  润新知