最长的包含K个点的简单路径 java,[BZOJ4016][FJOI2014]最短路径树问题

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

试题描述

给一个包含n个点,m条边的无向连通图。从顶点1出发,往其余所有点分别走一次并返回。

往某一个点走时,选择总长度最短的路径走。若有多条长度最短的路径,则选择经过的顶点序列字典序最小的那条路径(如路径A为1,32,11,路径B为1,3,2,11,路径B字典序较小。注意是序列的字典序的最小,而非路径中节点编号相连的字符串字典序最小)。到达该点后按原路返回,然后往其他点走,直到所有点都走过。

可以知道,经过的边会构成一棵最短路径树。请问,在这棵最短路径树上,最长的包含K个点的简单路径长度为多长?长度为该最长长度的不同路径有多少条?

这里的简单路径是指:对于一个点最多只经过一次的路径。不同路径是指路径两端端点至少有一个不同,点A到点B的路径和点B到点A视为同一条路径。

输入

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

输出

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

输入示例

输出示例

数据规模及约定

对于所有数据n<=30000,m<=60000,2<=K<=n。数据保证最短路径树上至少存在一条长度为K的路径。

题解

对于每一个点的出边按照目标点编号从小到大排序,跑一边 Dijkstra,构造出树,再套点分治。

#include

#include

#include

#include

#include

#include

#include

#include

using namespace std;

int read() {

int x = 0, f = 1; char c = getchar();

while(!isdigit(c)){ if(c == '-') f = -1; c = getchar(); }

while(isdigit(c)){ x = x * 10 + c - '0'; c = getchar(); }

return x * f;

}

#define maxn 30010

#define maxm 60010

#define oo 2147483647

int n, m, M, K;

struct Edge {

int v, w;

Edge() {}

Edge(int _, int __): v(_), w(__) {}

bool operator < (const Edge& t) const { return v < t.v; }

} ;

vector E[maxn];

bool vis[maxn];

int d[maxn], fa[maxn], fad[maxn];

struct Node {

int u, d;

Node() {}

Node(int _, int __): u(_), d(__) {}

bool operator < (const Node& t) const { return d > t.d; }

} ;

priority_queue Q;

void Dijkstra() {

for(int i = 1; i <= n; i++) d[i] = oo;

d[1] = 0;

Q.push(Node(1, 0));

while(!Q.empty()) {

int u = Q.top().u; Q.pop();

if(vis[u]) continue;

vis[u] = 1;

for(int i = 0; i < E[u].size(); i++)

if(d[E[u][i].v] > d[u] + E[u][i].w) {

d[E[u][i].v] = d[u] + E[u][i].w;

fa[E[u][i].v] = u; fad[E[u][i].v] = E[u][i].w;

if(!vis[E[u][i].v]) Q.push(Node(E[u][i].v, d[E[u][i].v]));

}

}

return ;

}

int head[maxn], to[maxm], next[maxm], dist[maxm];

void AddEdge(int a, int b, int c) {

to[++m] = b; dist[m] = c; next[m] = head[a]; head[a] = m;

swap(a, b);

to[++m] = b; dist[m] = c; next[m] = head[a]; head[a] = m;

return ;

}

int root, size, siz[maxn], f[maxn], ans, ansc;

void getroot(int u, int pa) {

siz[u] = 1; f[u] = 0;

for(int e = head[u]; e; e = next[e]) if(!vis[to[e]] && to[e] != pa) {

getroot(to[e], u);

siz[u] += siz[to[e]];

f[u] = max(f[u], siz[to[e]]);

}

f[u] = max(f[u], size - siz[u]);

if(f[u] < f[root]) root = u;

return ;

}

int A[maxn], Ac[maxn], B[maxn], Bc[maxn], mxd;

void dfs(int u, int d, int dep, int pa) {

mxd = max(mxd, dep);

//printf("XXX: %d %d %d\n", u, d, dep);

if(!Ac[dep] || A[dep] < d) A[dep] = d, Ac[dep] = 1;

else if(A[dep] == d) Ac[dep]++;

for(int e = head[u]; e; e = next[e]) if(!vis[to[e]] && to[e] != pa)

dfs(to[e], d + dist[e], dep + 1, u);

return ;

}

void solve(int u) {

//printf("u: %d\n", u);

vis[u] = 1;

int Mxd = 0;

for(int e = head[u]; e; e = next[e]) if(!vis[to[e]]) {

mxd = 0;

dfs(to[e], dist[e], 1, u);

Mxd = max(Mxd, mxd);

Ac[0] = Bc[0] = 1;

//for(int i = 1; i <= mxd; i++) printf("here: %d(%d) ", A[i], Ac[i]); putchar('\n');

for(int i = 1; i <= min(K, mxd); i++)

if(!ansc || ans < A[i] + B[K-i]) ans = A[i] + B[K-i], ansc = Ac[i] * Bc[K-i];

else if(ans == A[i] + B[K-i]) ansc += Ac[i] * Bc[K-i];

for(int i = 1; i <= mxd; i++) {

if(!Bc[i] || B[i] < A[i]) B[i] = A[i], Bc[i] = Ac[i];

else if(B[i] == A[i]) Bc[i] += Ac[i];

A[i] = Ac[i] = 0;

}

}

for(int i = 1; i <= Mxd; i++) B[i] = Bc[i] = 0;

for(int e = head[u]; e; e = next[e]) if(!vis[to[e]]) {

root = 0; f[0] = n + 1; size = siz[u]; getroot(to[e], u);

solve(root);

}

return ;

}

int main() {

n = read(); M = read(); K = read() - 1;

for(int i = 1; i <= M; i++) {

int a = read(), b = read(), c = read();

E[a].push_back(Edge(b, c)); E[b].push_back(Edge(a, c));

}

for(int i = 1; i <= n; i++) sort(E[i].begin(), E[i].end());

Dijkstra();

for(int i = 2; i <= n; i++) AddEdge(i, fa[i], fad[i]);

//for(int i = 1; i <= n; i++) printf("%d ", fa[i]); putchar('\n');

memset(vis, 0, sizeof(vis));

root = 0; f[0] = n + 1; size = n; getroot(1, 0);

solve(root);

printf("%d %d\n", ans, ansc);

return 0;

}

简直是强行乱套

&lbrack;BZOJ4016&rsqb;&lbrack;FJOI2014&rsqb;最短路径树问题&lpar;dijkstra&plus;点分治&rpar;

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

【BZOJ4016】&lbrack;FJOI2014&rsqb;最短路径树问题

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

【BZOJ4016】&lbrack;FJOI2014&rsqb;最短路径树问题 最短路径树&plus;点分治

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

【BZOJ4016】&lbrack;FJOI2014&rsqb;最短路径树问题(点分治,最短路)

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

bzoj 4016 &lbrack;FJOI2014&rsqb;最短路径树问题(最短路径树&plus;树分治)

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

BZOJ&lowbar;4016&lowbar;&lbrack;FJOI2014&rsqb;最短路径树问题&lowbar;最短路&plus;点分治

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

【BZOJ-4016】最短路径树问题 Dijkstra &plus; 点分治

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

&lbrack;FJOI2014&rsqb;最短路径树问题 长链剖分

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

洛谷 &lbrack;FJOI2014&rsqb;最短路径树问题 解题报告

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

随机推荐

&period;NET - 基于事件的异步模型

注:这是大概四年前写的文章了.而且我离开.net领域也有四年多了.本来不想再发表,但是这实际上是Active Object模式在.net中的一种重要实现方法,因此我把它掏出来发布一下.如果该模型有新的 ...

重写form 表单的验证信息

(function($) { var isformValidationPostBack=true; var isformValidation = false; $.extend({ formValid ...

使用Jsoup 爬取网易首页所有的图片

package com.enation.newtest; import java.io.File; import java.io.FileNotFoundException; import java. ...

apache开源项目--Syncope

Apache Syncope is an Open Source system for managing digital identities in enterprise environments, ...

Data transfer object

Data transfer object (DTO) is a design pattern used to transfer data between software application su ...

【socket&period;io研究】2&period;小试牛刀

1.建立个项目,也就是文件夹,这里使用testsocket 2.创建文件package.json,用于描述项目: { "name":"testsocket", ...

L8&lowbar;2

4.留下pid为12345的那个sh进程,杀死系统中所有其它sh进程 ps –ef|grep sh |awk ‘{if($2!=”12345”) {print “kill “$2}}’ >kil ...

R语言与分类算法的绩效评估(转)

关于分类算法我们之前也讨论过了KNN.决策树.naivebayes.SVM.ANN.logistic回归.关于这么多的分类算法,我们自然需要考虑谁的表现更加的优秀. 既然要对分类算法进行评价,那么我们 ...

truffle 安装以及基本指令

1. linux下安装方式 $ npm install -g truffle 环境要求: NodeJS 5.0+ Windows,Linux,或Mac OS X 2. 创建工程: $ mkdir te ...

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值