bzoj 4016 [FJOI2014]最短路径树问题(最短路径树+树分治)
4016: [FJOI2014]最短路径树问题
Time Limit: 5 Sec Memory Limit: 512 MB
Submit: 426 Solved: 147
[Submit][Status][Discuss]
Description
径B为1,3,2,11,路径B字典序较小。注意是序列的字典序的最小,而非路径中节点编号相连的字符串字典序最小)。到达该点后按原路返回,然后往其他
点走,直到所有点都走过。
Input
n个点m条边,要求的路径需要经过K个点。接下来输入m行,每行三个正整数Ai,Bi,Ci(1<=Ai,Bi<=n,1<=Ci&
lt;=10000),表示Ai和Bi间有一条长度为Ci的边。数据保证输入的是连通的无向图。
Output
Sample Input
1 2 1
2 3 1
3 4 1
2 5 1
3 6 1
5 6 1
Sample Output
HINT
对于所有数据n<=30000,m<=60000,2<=K<=n。数据保证最短路径树上至少存在一条长度为K的路径。
【思路】
先求出满足要求的最短路树来。
分治:求出过根节点的点对数,其它递归处理。
求过根节点的点对:假设现在处理根节点的S子树,用f[i][0]表示前S-1棵子树中与根相距i个节点(不含根)的最长路径,f[i][1]表示方案数,类似的定义tmp为当前S子树的统计结果。一遍bfs构造出tmp,枚举该子树上的结点数更新答案,然后用tmp更新f。
需要注意的有:
累计答案的诸多小细节。
f[][],tmp[][],queue的清零。
【代码】
#include<cstdio>
#include<vector>
#include<queue>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std; const int N = +;
const int INF = 1e9+1e9; struct Edge {
int v,w;
Edge(int v=,int w=):v(v),w(w) {}
bool operator < (const Edge& rhs) const {
return v<rhs.v;
}
};
queue<int> q;
int n,m,K,root,size,d[N],inq[N];
int ans1,ans2,siz[N],mx[N],vis[N],dep[N],dis[N],fa[N];
vector<Edge> g[N],G[N]; void spfa() {
for(int i=;i<=n;i++) d[i]=INF;
memset(inq,,sizeof(inq));
inq[]=; q.push();
while(!q.empty()) {
int u=q.front(); q.pop(); inq[u]=;
for(int i=;i<g[u].size();i++) {
int v=g[u][i].v,w=g[u][i].w;
if(d[v]>d[u]+w) {
d[v]=d[u]+w;
if(!inq[v]) inq[v]=,q.push(v);
}
}
}
}
void dfs(int u) {
vis[u]=;
for(int i=;i<g[u].size();i++) {
int v=g[u][i].v,w=g[u][i].w;
if(!vis[v] && d[v]==d[u]+w) {
G[u].push_back(Edge(v,w));
G[v].push_back(Edge(u,w));
dfs(v);
}
}
}
void getroot(int u) {
siz[u]=; mx[u]=;
for(int i=;i<G[u].size();i++) {
int v=G[u][i].v;
if(v!=fa[u] && !vis[v]) {
fa[v]=u;
getroot(v);
siz[u]+=siz[v];
if(siz[v]>mx[u]) mx[u]=siz[v];
}
}
mx[u]=max(mx[u],size-siz[u]);
if(mx[u]<mx[root]) root=u;
}
int f[N][],tmp[N][];
void solve(int u,int S){
vis[u]=; f[][]=;
int m=G[u].size();
for(int i=;i<m;i++) {
int v=G[u][i].v;
if(!vis[v]) {
while(!q.empty()) q.pop(); //clear
q.push(v),dep[v]=,dis[v]=G[u][i].w,fa[v]=u;
while(!q.empty()) {
int now=q.front(); q.pop();
int k=dep[now];
if(k>K) break;
if(dis[now]>tmp[k][])
tmp[k][]=dis[now],tmp[k][]=;
if(dis[now]==tmp[k][]) tmp[k][]++;
for(int j=;j<G[now].size();j++) {
int to=G[now][j].v;
if(!vis[to] && to!=fa[now]) {
fa[to]=now;
dep[to]=dep[now]+;
dis[to]=dis[now]+G[now][j].w;
q.push(to);
}
}
}
//for(int j=1;j<=K;j++) printf("(%d,%d) ",tmp[j][0],tmp[j][1]);cout<<endl;
for(int j=;j<=K;j++) { //tmp位于前可以取[1..K]
if(tmp[j][]+f[K-j][]>ans1)
ans1=tmp[j][]+f[K-j][],ans2=;
if(tmp[j][]+f[K-j][]==ans1)
ans2+=tmp[j][]*f[K-j][];
}
for(int j=;j<=K;j++) {
if(tmp[j][]>f[j][]) f[j][]=tmp[j][],f[j][]=;
if(tmp[j][]==f[j][]) f[j][]+=tmp[j][];
tmp[j][]=tmp[j][]=;
}
}
}
//cout<<u<<": "<<ans1<<" "<<ans2<<endl;
for(int j=;j<=K;j++) f[j][]=f[j][]=;
m=G[u].size();
for(int i=;i<m;i++) {
int v=G[u][i].v;
if(!vis[v]) {
size=siz[v];
if(siz[v]>siz[u]) siz[v]=S-siz[v];
root=;
if(size>=K) getroot(v);
solve(root,siz[v]);
}
}
}
void read(int& x) {
char c=getchar(); int f=; x=;
while(!isdigit(c)){if(c=='-') f=-;c=getchar();}
while(isdigit(c)) x=x*+c-'',c=getchar();
x*=f;
}
int main() {
//freopen("in.in","r",stdin);
//freopen("out.out","w",stdout);
read(n),read(m),read(K); K--;
int u,v,w;
for(int i=;i<m;i++) {
read(u),read(v),read(w);
g[u].push_back(Edge(v,w));
g[v].push_back(Edge(u,w));
}
for(int i=;i<=n;i++)
sort(g[i].begin(),g[i].end());
spfa();
memset(vis,,sizeof(vis));
dfs();
size=n; mx[]=INF; root=;
memset(vis,,sizeof(vis));
getroot() , solve(root,size);
printf("%d %d",ans1,ans2);
return ;
}
bzoj 4016 [FJOI2014]最短路径树问题(最短路径树+树分治)的更多相关文章
- bzoj 4016: [FJOI2014]最短路径树问题
bzoj4016 最短路路径问题 Time Limit: 5 Sec Memory Limit: 512 MB Description 给一个包含n个点,m条边的无向连通图.从顶点1出发,往其余所有点 ...
- BZOJ 4016: [FJOI2014]最短路径树问题( 最短路 + 点分治 )
先跑出最短路的图, 然后对于每个点按照序号从小到大访问孩子, 就可以搞出符合题目的树了. 然后就是经典的点分治做法了. 时间复杂度O(M log N + N log N) -------------- ...
- BZOJ 4016 [FJOI2014]最短路径树问题 (贪心+点分治)
题目大意:略 传送门 硬是把两个题拼到了一起= = $dijkstra$搜出单源最短路,然后$dfs$建树,如果$dis_{v}=dis_{u}+e.val$,说明这条边在最短路图内,然后像$NOIP ...
- Bzoj4016/洛谷P2993 [FJOI2014] 最短路径树问题(最短路径问题+长链剖分/点分治)
题面 Bzoj 洛谷 题解 首先把最短路径树建出来(用\(Dijkstra\),没试过\(SPFA\)\(\leftarrow\)它死了),然后问题就变成了一个关于深度的问题,可以用长链剖分做,所以我 ...
- “中兴捧月”比赛之——二叉查找树(BST)树的最短路径Java求解
问题描述: BST树,又称二叉查找树,求其到所有叶子节点路径的最小值 测试用例一: 10 5 20 返回15: 测试用例二: 100 20 70 110 120 10 null null 89 nu ...
- 经典树与图论(最小生成树、哈夫曼树、最短路径问题---Dijkstra算法)
参考网址: https://www.jianshu.com/p/cb5af6b5096d 算法导论--最小生成树 最小生成树:在连通网的所有生成树中,所有边的代价和最小的生成树,称为最小生成树. im ...
- [BZOJ 1576] [Usaco2009 Jan] 安全路经Travel 【树链剖分】
题目链接: BZOJ - 1576 题目分析 首先Orz Hzwer的题解. 先使用 dijikstra 求出最短路径树. 那么对于一条不在最短路径树上的边 (u -> v, w) 我们可以先沿 ...
- bzoj 1576 [Usaco2009 Jan]安全路经Travel(树链剖分,线段树)
[题意] 给定一个无向图,找到1-i所有的次短路经,要求与最短路径的最后一条边不重叠. [思路] 首先用dijkstra算法构造以1为根的最短路树. 将一条无向边看作两条有向边,考察一条不在最短路树上 ...
- 主席树||可持久化线段树+离散化 || 莫队+分块 ||BZOJ 3585: mex || Luogu P4137 Rmq Problem / mex
题面:Rmq Problem / mex 题解: 先离散化,然后插一堆空白,大体就是如果(对于以a.data<b.data排序后的A)A[i-1].data+1!=A[i].data,则插一个空 ...
随机推荐
- PAT_1007 素数对猜想
今天想更的那道题现在还没A出来.先把下午做的一道题更新了吧.快零点了.无奈啊. 问题描述: 让我们定义 dn 为:dn = pn+1 - pn,其中 pi 是第i个素数.显然有 d1=1 且对于n&g ...
- leetcode problem 31 -- Next Permutation
Implement next permutation, which rearranges numbers into the lexicographically next greater permuta ...
- 《JavaScript高级程序设计》笔记(3):传递参数
待更新... 9.17更新: ECMAScript中所有函数的参数都是按值传递的.也就是说,把函数外部复制给函数内部的参数,就和把值从一个变量复制到另一个变量一样.基本类型值的传递如同基本类型变量的复 ...
- javascript 事件对象
1.事件对象 用来记录一些事件发生时的相关信息的对象 A.只有当事件发生的时候才产生,只能在处理函数内部访问 B.处理函数运行结束后自动销毁2.如何获取事件对象 IE: window.even ...
- Day9 网络编程
OSI(Open System Interconnect),即开放式系统互联. ISO(International Standards Organization)国际标准化组织 OSI七层模型: TC ...
- SQL 多条件查询
网上有不少人提出过类似的问题:“看到有人写了WHERE 1=1这样的SQL,到底是什么意思?”.其实使用这种用法的开发人员一般都是在使用动态组装的SQL.让我们想像如下的场景:用户要求提供一个灵活的查 ...
- poj 3185 The Water Bowls
The Water Bowls 题意:给定20个01串(最终的状态),每个点变化时会影响左右点,问最终是20个0所需最少操作数? 水题..直接修改增广矩阵即可:看来最优解不是用高斯消元(若是有Gaus ...
- LDR伪指令与ADR伪指令的区别
测试代码 ldr r0, _start adr r0, _start ldr r0, =_start nop mov pc, lr _start: nop 设置代码的起始地址为 0x0c008000, ...
- Java 之 网络编程
1.OSI模型 a.全称:开放系统互联 b.七层模型:应用层.表示层.会话层.传输层.网络层.数据链路层.物理层 c.注意:OSI模型 是所谓的 理论标准 2.TCP/IP模型 a.四层模型:应用层. ...
- html 各个标签初始化
html,body,div,ul,li,ol,h1,h2,h3,h4,h5,h6,span,input{ margin:0;padding:0;}body{font:12px/1.5em " ...