http://www.lydsy.com/JudgeOnline/problem.php?id=4016 (题目链接)

题意

  给出一张无向图,求出它的最小路径树,然后求最小路径树上节点数为${K}$的最长路径,并求出这样的路径有多少条。

Solution

  mdzz看错题了,以为求路径条数的时候对节点个数没有要求。。

  抠最小路径树有点恶心,还对字典序有要求,参见了DaD3zZ的方法,枚举边,将符合距离条件的连边,然后dfs,优先字典序小的。

  至于点分治,就是两个数组搞一搞,挺简单的一个统计。

细节

  不要乱用memset,不然复杂度就不对了。

  这种比较长的程序写在namespace或者结构体里面会比较清晰吧。

代码

// bzoj4016
#include<algorithm>
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<cstdio>
#include<vector>
#include<cmath>
#include<queue>
#include<map>
#define LL long long
#define inf 1ll<<30
#define Pi acos(-1.0)
#define free(a) freopen(a".in","r",stdin),freopen(a".out","w",stdout);
using namespace std; const int maxn=30010,maxm=60010;
int vis[maxn],deep[maxn],f[maxn],size[maxn],head[maxn];
int n,m,K,cnt,sum,Dargen;
int ans1;LL ans2; struct edge {int from,to,next,w;}e[maxm<<1]; namespace Prepare {
int dis[maxn];
vector<int> v[maxn];
struct data {
int num,w;
friend bool operator < (const data a,const data b) {
return a.w>b.w;
}
}; void link(int u,int v,int w) {
e[++cnt]=(edge){u,v,head[u],w};head[u]=cnt;
e[++cnt]=(edge){v,u,head[v],w};head[v]=cnt;
}
void Dijkstra() {
priority_queue<data> q;
for (int i=1;i<=n;i++) dis[i]=inf;
q.push((data){1,0});dis[1]=0;
while (!q.empty()) {
data x=q.top();q.pop();
if (vis[x.num]) continue;
vis[x.num]=1;
for (int i=head[x.num];i;i=e[i].next)
if (!vis[e[i].to] && dis[e[i].to]>x.w+e[i].w) {
dis[e[i].to]=x.w+e[i].w;
q.push((data){e[i].to,dis[e[i].to]});
}
}
for (int i=1;i<=cnt;i++) {
int uu=e[i].from,vv=e[i].to,ww=e[i].w;
if (dis[uu]+ww==dis[vv]) v[uu].push_back(vv);
}
}
void build(int x) {
vis[x]=1;
sort(v[x].begin(),v[x].end());
int l=v[x].size();
for (int i=0;i<l;i++) if (!vis[v[x][i]]) {
link(x,v[x][i],dis[v[x][i]]-dis[x]);
build(v[x][i]);
}
}
} namespace NodeDivide {
int D[maxn],d[maxn],cntd[maxn],cntD[maxn]; void caldargen(int x,int fa) {
size[x]=1;f[x]=0;
for (int i=head[x];i;i=e[i].next) if (!vis[e[i].to] && e[i].to!=fa) {
caldargen(e[i].to,x);
size[x]+=size[e[i].to];
f[x]=max(f[x],size[e[i].to]);
}
f[x]=max(f[x],sum-size[x]);
if (f[x]<f[Dargen]) Dargen=x;
}
void caldeep(int x,int fa,int l) {
if (d[deep[x]]<l) d[deep[x]]=l,cntd[deep[x]]=1;
else if (d[deep[x]]==l) cntd[deep[x]]++;
for (int i=head[x];i;i=e[i].next) if (e[i].to!=fa && !vis[e[i].to]) {
deep[e[i].to]=deep[x]+1;
caldeep(e[i].to,x,l+e[i].w);
}
}
void work(int x) {
vis[x]=1;
for (int i=head[x];i;i=e[i].next) if (!vis[e[i].to]) {
deep[e[i].to]=1;
caldeep(e[i].to,0,e[i].w);
for (int j=1;d[j] && j<K;j++) {
if (ans1<D[K-1-j]+d[j]) {
ans1=D[K-1-j]+d[j];
ans2=(LL)cntD[K-1-j]*cntd[j];
}
else if (ans1==D[K-1-j]+d[j]) ans2+=(LL)cntD[K-1-j]*cntd[j];
}
for (int j=1;d[j];j++) {
if (D[j]<d[j]) D[j]=d[j],cntD[j]=cntd[j];
else if (D[j]==d[j]) cntD[j]+=cntd[j];
d[j]=cntd[j]=0;
}
}
for (int i=1;D[i];i++) D[i]=cntD[i]=0;
for (int i=head[x];i;i=e[i].next) if (!vis[e[i].to] && size[e[i].to]>=K) {
Dargen=0;sum=size[e[i].to];
caldargen(e[i].to,0);
work(Dargen);
}
}
void Init() {
memset(vis,0,sizeof(vis));
f[0]=inf;sum=n;cntD[0]=1;
Dargen=0;caldargen(1,0);
work(Dargen);
}
} int main() {
scanf("%d%d%d",&n,&m,&K);
for (int u,v,w,i=1;i<=m;i++) {
scanf("%d%d%d",&u,&v,&w);
Prepare::link(u,v,w);
}
Prepare::Dijkstra();
memset(head,0,sizeof(head));
memset(vis,0,sizeof(vis));
cnt=0;
Prepare::build(1);
NodeDivide::Init();
printf("%d %lld",ans1,ans2);
return 0;
}

【bzoj4016】 FJOI2014—最短路径树问题的更多相关文章

  1. [BZOJ4016][FJOI2014]最短路径树问题

    [BZOJ4016][FJOI2014]最短路径树问题 试题描述 给一个包含n个点,m条边的无向连通图.从顶点1出发,往其余所有点分别走一次并返回. 往某一个点走时,选择总长度最短的路径走.若有多条长 ...

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

    4016: [FJOI2014]最短路径树问题 Time Limit: 5 Sec  Memory Limit: 512 MBSubmit: 1796  Solved: 625[Submit][Sta ...

  3. 【BZOJ4016】[FJOI2014]最短路径树问题

    [BZOJ4016][FJOI2014]最短路径树问题 题面 bzoj 洛谷 题解 虽然调了蛮久,但是思路还是蛮简单的2333 把最短路径树构出来,然后点分治就好啦 ps:如果树构萎了,这组数据可以卡 ...

  4. 【BZOJ4016】[FJOI2014]最短路径树问题 最短路径树+点分治

    [BZOJ4016][FJOI2014]最短路径树问题 Description 给一个包含n个点,m条边的无向连通图.从顶点1出发,往其余所有点分别走一次并返回. 往某一个点走时,选择总长度最短的路径 ...

  5. 【BZOJ4016】[FJOI2014]最短路径树问题(点分治,最短路)

    [BZOJ4016][FJOI2014]最短路径树问题(点分治,最短路) 题面 BZOJ 洛谷 题解 首先把最短路径树给构建出来,然后直接点分治就行了. 这个东西似乎也可以长链剖分,然而没有必要. # ...

  6. bzoj 4016 [FJOI2014]最短路径树问题(最短路径树+树分治)

    4016: [FJOI2014]最短路径树问题 Time Limit: 5 Sec  Memory Limit: 512 MBSubmit: 426  Solved: 147[Submit][Stat ...

  7. BZOJ_4016_[FJOI2014]最短路径树问题_最短路+点分治

    BZOJ_4016_[FJOI2014]最短路径树问题_最短路+点分治 Description 给一个包含n个点,m条边的无向连通图.从顶点1出发,往其余所有点分别走一次并返回. 往某一个点走时,选择 ...

  8. 【BZOJ-4016】最短路径树问题 Dijkstra + 点分治

    4016: [FJOI2014]最短路径树问题 Time Limit: 5 Sec  Memory Limit: 512 MBSubmit: 1092  Solved: 383[Submit][Sta ...

  9. [FJOI2014]最短路径树问题 长链剖分

    [FJOI2014]最短路径树问题 LG传送门 B站传送门 长链剖分练手好题. 如果你还不会长链剖分的基本操作,可以看看我的总结. 这题本来出的很没水平,就是dijkstra(反正我是不用SPFA)的 ...

  10. 洛谷 [FJOI2014]最短路径树问题 解题报告

    [FJOI2014]最短路径树问题 题目描述 给一个包含\(n\)个点,\(m\)条边的无向连通图.从顶点\(1\)出发,往其余所有点分别走一次并返回. 往某一个点走时,选择总长度最短的路径走.若有多 ...

随机推荐

  1. 廖雪峰git教程学习笔记2

    本地git仓库和github仓库之间的传输是通过SSH加密的,所以: 注册GitHub账号 创建SSH key.在用户主目录下,看看有没有.ssh目录,如果有,再看看这个目录下有没有id_rsa和id ...

  2. String字符串的方法

    String字符串在Java开发中是我们常用的一种数据类型,同时String字符串也为我们提供了大量的方法.通过一些实例的练习,我们可以对String字符串的方法有一个比较清楚的了解. 有一个字符串S ...

  3. 1分钟入门接口自动化框架Karate

    介绍 在这篇文章中,我们将介绍一下开源的Web-API自动化测试框架——Karate Karate是基于另一个BDD测试框架Cucumber来建立的,并且共用了一些相同的思想.其中之一就是使用Gher ...

  4. ahk打印成pdf记录

    软工课程后记: 要求将博客打印成pdf存档.为了偷懒,不想自己点鼠标一个个保存,所以写了一个ahk小程序.博客教程推荐,建议一试,不难.还很方便.我也只学了点点皮毛,满足需求即止. 第一个成功的小例子 ...

  5. 【Alpha】阶段第八次Scrum Meeting

    [Alpha]阶段第八次Scrum Meeting 工作情况 团队成员 今日已完成任务 明日待完成任务 刘峻辰 编写按学院搜索课程接口 编写获得所有学院接口 赵智源 构建前测试点测试框架 编写alph ...

  6. iOS自学-监听按钮点击、提醒框

    //事件监听的问题 CGRect btn2Frame = CGRectMake(100.0, 150.0, 60.0, 44.0); //两种不同的方式创建 UIButton *btn2 = [UIB ...

  7. 进阶系列(12)—— C#异步编程

    一.What's 异步? 启动程序时,系统会在内存中创建一个新的进程.进程是构成运行程序资源的集合. 在进程内部,有称为线程的内核对象,它代表的是真正的执行程序.系统会在 Main 方法的第一行语句就 ...

  8. <s:action>的一些用法

    Action标签,顾名思义,是用来调用Action的标签,在JSP中页面中,可以具体指定某一命名空间中的某一Action.而标签的主体用于显示及渲染Actionr的处理结果. action标签有如下几 ...

  9. sprint初步计划(第一天)

    一.现状 小组成员初步了解四则运算程序编写大概内容,进行简单的讨论.只知道大概的流程,实际还没做出.现在明确目标是把我们写Java的四则运算变成一个手机APP,关于手机ap,我们还不是很了解,所以需要 ...

  10. wcf的DataContractAttribute与DataMenmberAttribute

    文章:序列化和反序列化的几种方式(DataContractSerializer)(二) 介绍了序列化控制细节.哪些字段可以序列化,序列化后这些字段的名字.