先用dijkstra把最短路树建出来,然后就是树的质心分治了。

经过k个点的路径,要么全在子树上,要么经过根结点,因此可以分治。

如果分治的时候选点不好会变成O(n^2),比较极端的情况是比如树是一条链。

选择质心可以保证最大子树结点不超过n/2,每次递归至少减半,递归层数是O(logn)的。

找子树质心是O(n)的树形dp,枚举到根结点的路径是O(n)的。

把经过根节点并且路径上有c个结点的最长路径以及方案保存到一个map,对于一条新增的路径去查找k-c个点的路径,就可以更新答案了。

如果用的unorder_map,那么查找是O(1)的,因此分治复杂度是T(n) = 2*T(n/2) + O(n) ≈ O(nlogn)。

总体复杂度是O(mlogn + nlogn)

/*********************************************************
* ------------------ *
* author AbyssFish *
**********************************************************/
#include<cstdio>
#include<iostream>
#include<string>
#include<cstring>
#include<queue>
#include<vector>
#include<stack>
#include<map>
#include<set>
#include<algorithm>
#include<cmath>
#include<numeric>
#include<climits>
#include<unordered_map>
using namespace std; const int maxn = +;
const int maxm = *+; typedef long long ll;
#define sInt 4
int hd[maxn], nx[maxm], to[maxm], we[maxm], ec;
#define eachedge int i = hd[u]; ~i; i = nx[i]
void init_g(int n){ memset(hd+,0xff,sInt*n); ec = ; }
void add_edge(int u,int v,int c)
{
to[ec] = v;
we[ec] = c;
nx[ec] = hd[u];
hd[u] = ec++;
} int n,m,k; int di[maxn], fe[maxn];
typedef pair<int,int> pii;
#define dist first
#define ver second
priority_queue<pii,vector<pii>,greater<pii> > q; void dijkstra()
{
memset(di+,0x3f,sInt*n); di[] = ; fe[] = -;
q.push(pii(,));
while(!q.empty()){
pii x = q.top(); q.pop();
if(x.dist != di[x.ver]) continue;
int u = x.ver;
for(int i = hd[u]; ~i; i = nx[i]){
int v = to[i];
if(di[v] > di[u] + we[i]){
di[v] = di[u]+we[i];
fe[v] = i;
q.push(pii(di[v],v));
}
else if(di[v] == di[u] + we[i] && to[fe[v]^] > u){
fe[v] = i;
}
}
}
} void rewrite(int u,int i)
{
nx[i] = hd[u];
hd[u] = i;
} void build_tree()
{
dijkstra();
init_g(n);
for(int v = ; v <= n; v++){
int e = fe[v];
int u = to[e^];
rewrite(u,e);
rewrite(v,e^);
}
} bool vis_c[maxn];
int tr_sz[maxn]; void cal_tr_sz(int u,int f)
{
int &c = tr_sz[u];
c = ;
for(eachedge){
int v = to[i];
if(v == f || vis_c[v]) continue;
c += tr_sz[v];
cal_tr_sz(v,u);
}
} int block_size;
int best, centroid;
void findCentroid(int u,int f)
{
int mx = ;
for(eachedge){
int v = to[i];
if(v == f || vis_c[v]) continue;
findCentroid(v,u);
mx = max(mx, tr_sz[v]);
}
mx = max(mx,block_size-tr_sz[u]);
if(best > mx){
best = mx;
centroid = u;
}
} typedef unordered_map<int,pii> cont;
typedef cont::iterator con_it;
//key 经过的点数,value(最长距离,方案数)
cont prv;
cont tmp; void update(cont &res,int c, const pii &np)
{
con_it it = res.find(c);
if(it != res.end()){
pii &p = it->second;
if(p.dist == np.dist) p.ver += np.ver;
else if(p.dist < np.dist) {
p = np;
}
}
else {
res.insert(make_pair(c,np));
}
} void enum_path(int u,int f,int c,int d,cont &res)
{
if(c >= k) return;
update(res,c,pii(d,)); for(eachedge){
int v = to[i];
if(v == f || vis_c[v]) continue;
enum_path(v,u,c+,d+we[i],res);
}
} int ans;
ll cnt; void divide(int rt)
{
cal_tr_sz(rt,-);
best = INT_MAX;
block_size = tr_sz[rt];
findCentroid(rt,-);
int u = centroid;
vis_c[u] = true; for(eachedge){
if(!vis_c[to[i]]) divide(to[i]);
} prv.clear();
prv.insert(make_pair(,pii(,)));
for(eachedge){
if(vis_c[to[i]]) continue;
tmp.clear();
enum_path(to[i],u,,we[i],tmp);
con_it it, it2;
for(it = tmp.begin(); it != tmp.end(); it++){
int c = it->first;
pii &p = it->second;
if((it2 = prv.find(k-c)) != prv.end()){
ll dis = it2->second.dist + p.dist;
if(dis > ans){
ans = dis; cnt = p.ver * it2->second.ver;
}
else if(dis == ans) cnt += p.ver * it2->second.ver;
}
} for(it = tmp.begin(); it != tmp.end(); it++){
int c = it->first+;
update(prv,c,it->second);
}
} vis_c[u] = false;
} void solve()
{
build_tree();
ans = cnt = ;
divide();
printf("%d %lld\n",ans,cnt);
} void init()
{
scanf("%d%d%d",&n,&m,&k);
init_g(n);
for(int i = ; i < m; i++){
int a,b,c; scanf("%d%d%d",&a,&b,&c);
add_edge(a,b,c);
add_edge(b,a,c);
}
} //#define LOCAL
int main()
{
#ifdef LOCAL
freopen("in.txt","r",stdin);
#endif
int T; scanf("%d",&T);
while(T--){
init();
solve();
}
return ;
}

HDU 4871 Shortest-path tree的更多相关文章

  1. hdu 3631 Shortest Path(Floyd)

    题目链接:pid=3631" style="font-size:18px">http://acm.hdu.edu.cn/showproblem.php?pid=36 ...

  2. HDU 5636 Shortest Path 暴力

    Shortest Path 题目连接: http://acm.hdu.edu.cn/showproblem.php?pid=5636 Description There is a path graph ...

  3. HDU 5636 Shortest Path(Floyed,枚举)

    Shortest Path Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Others) Tot ...

  4. HDU - 3631 Shortest Path(Floyd最短路)

    Shortest Path Time Limit: 1000MS Memory Limit: 32768KB 64bit IO Format: %I64d & %I64u SubmitStat ...

  5. HDU - 4725_The Shortest Path in Nya Graph

    The Shortest Path in Nya Graph Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (J ...

  6. hdu 3631 Shortest Path

    floyd算法好像很奇妙的样子.可以做到每次加入一个点再以这个点为中间点去更新最短路,效率是n*n. #include<cstdio> #include<cstring> #i ...

  7. HDU 5636 Shortest Path

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5636 题解: 1.暴力枚举: #include<cmath> #include<c ...

  8. HDU 5636 Shortest Path 分治+搜索剪枝

    题意:bc round 74 分析(官方题解): 你可以选择分类讨论, 但是估计可能会写漏一些地方. 只要抽出新增边的端点作为关键点, 建立一个新图, 然后跑一遍floyd就好了. 复杂度大概O(6^ ...

  9. HDU 5636 Shortest Path(Floyd)

    题目链接  HDU5636 n个点,其中编号相邻的两个点之间都有一条长度为1的边,然后除此之外还有3条长度为1的边. m个询问,每次询问求两个点之前的最短路. 我们把这三条边的6个点两两算最短路, 然 ...

  10. HDU 4479 Shortest path 带限制最短路

    题意:给定一个图,求从1到N的递增边权的最短路. 解法:类似于bellman-ford思想,将所有的边先按照权值排一个序,然后依次将边加入进去更新,每条边只更新一次,为了保证得到的路径是边权递增的,每 ...

随机推荐

  1. VS2015+NUnit+OpenCover 完成单元测试代码覆盖率测试

    1.VS2015+NUnit+OpenCover 完成单元测试代码覆盖率测试 https://download.csdn.net/download/qq_39441918/10522539 2.*注意 ...

  2. element-ui表单验证(电话,邮箱)

    element-ui Form表单验证 最近刚好使用了element-ui的form表单,官网只提供的示例,这里把一些常用的验证记录下来,方便后期查找最终的效果是这样的, 这个表单里还加入了一下其他组 ...

  3. find 根据时间查找,详解

    https://blog.csdn.net/u010181136/article/details/73322738 find可谓是aix/linux上使用较多的维护用命令,但很多时候需要用到针对时间的 ...

  4. Dev Express Report 学习总结(三)关于子报表Sub-Report的使用

    子报表即在一个Report(主报表)中嵌入另一个Report(子报表),从理论上来讲,任何一个Report都可以作为一个子报表,但在实际使用过程中,只有主报表和子报表构成一对多关系时才会使用子报表.使 ...

  5. Android NDK开发 JNI类型签名和方法签名(六)

    在Java存在两种数据类型: 基本类型 和 引用类型 ,大家都懂的 . 在JNI的世界里也存在类似的数据类型,与Java比较起来,其范围更具严格性,如下: 1.primitive types ---- ...

  6. 牛客网Java刷题知识点之泛型概念的提出、什么是泛型、泛型在集合中的应用、泛型类、泛型方法、泛型接口、泛型限定上限、泛型限定下限、 什么时候使用上限?泛型限定通配符的体现

    不多说,直接上干货! 先来看个泛型概念提出的背景的例子. GenericDemo.java package zhouls.bigdata.DataFeatureSelection; import ja ...

  7. DedeCms中Channel用typeid无效

    DedeCms中channel 用typeid调用无法达目的吗?请换成type试试! {dede:channel type='son' typeid='19' row='1'} <a href= ...

  8. idea创建Javaweb项目

    1.Javaweb项目结构 1.1修改生成.class文件的位置为WEB-INF下的classes: 生成的.class文件位置: 1.2 设置第三方jar包添加位置:

  9. JQuery中的prop和attr

    prop和attr都可以用来获取并改变对象的属性, 对于HTML元素本身就带有的固有属性,在处理时,使用prop方法. 对于HTML元素我们自己自定义的DOM属性,在处理时,使用attr方法. 栗子: ...

  10. ios 你必须了解的系统定义宏使用

    1. UNAVAILABLE_ATTRIBUTE __attribute__((unavailable)) - (instancetype)init UNAVAILABLE_ATTRIBUTE; 告诉 ...