题目大概要先求一张边有权的图的根为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=; i<=n; ++i){
  23. d[i]=INF; vis[i]=;
  24. }
  25. d[]=; vis[]=;
  26. queue<int> que;
  27. que.push();
  28. while(!que.empty()){
  29. int u=que.front(); que.pop();
  30. for(int i=head[u]; i!=-; 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]=;
  36. que.push(v);
  37. }
  38. }
  39. }
  40. vis[u]=;
  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]=;
  55. for(int i=head[u]; i!=-; 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]=;
  67. for(int i=head[u]; i!=-; 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!=-; 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]=;
  103. if(!tag[tot]){
  104. tag[tot]=;
  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!=-; 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+);
  114. }
  115. }
  116. void conqur(int u){
  117. an=;
  118. for(int i=head[u]; i!=-; i=edge[i].next){
  119. int v=edge[i].v;
  120. if(vis[v]) continue;
  121. bn=;
  122. conqur_dfs(v,v,edge[i].w,);
  123. for(int j=; j<bn; ++j){
  124. if(b_rec[j]==k-){
  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-){
  132. int tmp=k--b_rec[j];
  133. if(a_cnt[tmp]==) 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=; j<bn; ++j){
  143. int tmp=b_rec[j];
  144. tag[tmp]=;
  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]=;
  153. b_cnt[tmp]=;
  154. }
  155. }
  156. for(int i=; i<an; ++i){
  157. a_val[a_rec[i]]=;
  158. a_cnt[a_rec[i]]=;
  159. }
  160. }
  161.  
  162. void divide(int u){
  163. u=getcen(u);
  164. vis[u]=;
  165. conqur(u);
  166. for(int i=head[u]; i!=-; 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=;
  178. memset(head,-,sizeof(head));
  179. scanf("%d%d%d",&n,&m,&k);
  180. for(int i=; i<m; ++i){
  181. scanf("%d%d%d",&a,&b,&c);
  182. node[i<<].u=a; node[i<<].v=b; node[i<<].w=c;
  183. node[i<<|].u=b; node[i<<|].v=a; node[i<<|].w=c;
  184. }
  185. sort(node,node+(m<<));
  186. for(int i=; i<(m<<); ++i){
  187. addEdge(node[i].u,node[i].v,node[i].w);
  188. }
  189. SPFA(n);
  190. cnt=;
  191. memset(vis,,sizeof(vis));
  192. dfs();
  193. NE=;
  194. memset(head,-,sizeof(head));
  195. for(int i=; 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,,sizeof(vis));
  200. ans_val=; ans_cnt=;
  201. divide();
  202. printf("%d %d\n",ans_val,ans_cnt);
  203. }
  204. return ;
  205. }

HDU4871 Shortest-path tree(最短路径树 + 树的点分治)的更多相关文章

  1. 【CF938G】Shortest Path Queries(线段树分治,并查集,线性基)

    [CF938G]Shortest Path Queries(线段树分治,并查集,线性基) 题面 CF 洛谷 题解 吼题啊. 对于每个边,我们用一个\(map\)维护它出现的时间, 发现询问单点,边的出 ...

  2. ZOJ 2760 How Many Shortest Path(最短路径+最大流)

    Description Given a weighted directed graph, we define the shortest path as the path who has the sma ...

  3. Codeforces Round #329 (Div. 2) D. Happy Tree Party LCA/树链剖分

    D. Happy Tree Party     Bogdan has a birthday today and mom gave him a tree consisting of n vertecie ...

  4. HDU 4718 The LCIS on the Tree (动态树LCT)

    The LCIS on the Tree Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 65535/65535 K (Java/Oth ...

  5. hdu 5274 Dylans loves tree(LCA + 线段树)

    Dylans loves tree Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Othe ...

  6. 程序员的算法课(19)-常用的图算法:最短路径(Shortest Path)

    版权声明:本文为博主原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明. 本文链接:https://blog.csdn.net/m0_37609579/article/de ...

  7. LuoguP3690 【模板】Link Cut Tree (动态树) LCT模板

    P3690 [模板]Link Cut Tree (动态树) 题目背景 动态树 题目描述 给定n个点以及每个点的权值,要你处理接下来的m个操作.操作有4种.操作从0到3编号.点从1到n编号. 0:后接两 ...

  8. paip.tree 生成目录树到txt后的折叠查看

    paip.tree 生成目录树到txt后的折叠查看 作者Attilax ,  EMAIL:1466519819@qq.com  来源:attilax的专栏 地址:http://blog.csdn.ne ...

  9. 【BZOJ2588】Count On a Tree(主席树)

    [BZOJ2588]Count On a Tree(主席树) 题面 题目描述 给定一棵N个节点的树,每个点有一个权值,对于M个询问(u,v,k),你需要回答u xor lastans和v这两个节点间第 ...

  10. BZOJ_2212_[Poi2011]Tree Rotations_线段树合并

    BZOJ_2212_[Poi2011]Tree Rotations_线段树合并 Description Byteasar the gardener is growing a rare tree cal ...

随机推荐

  1. Mac 下 gradle 路径

    /Users/yourname/.gradle/wrapper/dists cmd:cd ~/.gradle/wrapper/dists/

  2. myeclipse相关

    :) MyEclipse 10.7以后开始支持JDK1.7,修改settings下面的配置文件没卵用.

  3. mysql扩展库-1

    启用mysql扩展库 在php.ini文件中去配置mysql扩展库 extension=php_mysql.dll 可以通过 phpinfo() 查看当前php支持什么扩展库. 在sql扩展库中创建一 ...

  4. jQuery – 3.JQuery的Dom操作

    3.1 JQuery的Dom操作     1.使用html()方法读取或者设置元素的innerHTML    2.使用text()方法读取或者设置元素的innerText     3.使用attr() ...

  5. map find 是线程安全的吗

    测试环境gcc4.8.2     iterator find ( const key_type& k ); const_iterator find ( const key_type& ...

  6. siblings 使用

    //$(object).siblings().each(function () { // $(this).find("img").attr("class", & ...

  7. 【20140113-2】MyEclipse生成javadoc时出错:编码GBK的不可映射字符

    今天生成java doc文档时,出现了如下所示的错误: 正在装入软件包 com.wisdom.test 的源文件...F:\workspace\StringUtils\src\com\wisdom\t ...

  8. [LeetCode] Validate Binary Search Tree (两种解法)

    Given a binary tree, determine if it is a valid binary search tree (BST). Assume a BST is defined as ...

  9. NPOI读写Excel

    1.整个Excel表格叫做工作表:WorkBook(工作薄),包含的叫页(工作表):Sheet:行:Row:单元格Cell. 2.NPOI是POI的C#版本,NPOI的行和列的index都是从0开始 ...

  10. NS2中trace文件分析

    ns中模拟出来的时间最终会以trace文件的形式告诉我们,虽然说一般都是用awk等工具分析trace文件,但是了解trace文件的格式也是必不可少的.下面就介绍一下无线网络模拟中trace文件的格式. ...