zoukankan      html  css  js  c++  java
  • [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 }
  • 相关阅读:
    HDU 1863 畅通工程(Kruskal)
    HDU 1879 继续畅通工程(Kruskra)
    HDU 1102 Constructing Roads(Kruskal)
    POJ 3150 Cellular Automaton(矩阵快速幂)
    POJ 3070 Fibonacci(矩阵快速幂)
    ZOJ 1648 Circuit Board(计算几何)
    ZOJ 3498 Javabeans
    ZOJ 3490 String Successor(模拟)
    Java实现 LeetCode 749 隔离病毒(DFS嵌套)
    Java实现 LeetCode 749 隔离病毒(DFS嵌套)
  • 原文地址:https://www.cnblogs.com/HocRiser/p/8421825.html
Copyright © 2011-2022 走看看