luogu 2993 [FJOI2014]最短路径树问题 Dijkstra+点分治
挺简单的,但是给人一种把两个问题强行弄到一起的感觉.
十分不好写.
Code:
#include <queue>
#include <cstdio>
#include <vector>
#include <algorithm>
#define N 100007
#define ll long long
#define inf 1000000004
#define setIO(s) freopen(s".in","r",stdin)
using namespace std;
int K,n,m;
namespace tree
{
ll answer;
int edges,root,sn,maxdep,tl,best;
int hd[N],to[N],nex[N],val[N];
int size[N],mx[N],vis[N],f[N],g[N],bu[N],cntf[N],cntg[N];
void addedge(int u,int v,int c)
{
nex[++edges]=hd[u],hd[u]=edges,to[edges]=v,val[edges]=c;
}
void getroot(int u,int ff)
{
size[u]=1,mx[u]=0;
for(int i=hd[u];i;i=nex[i])
{
int v=to[i];
if(!vis[v]&&v!=ff)
getroot(v,u), size[u]+=size[v], mx[u]=max(mx[u], size[v]);
}
mx[u]=max(mx[u],sn-size[u]);
if(mx[u]<mx[root]) root=u;
}
void dfs(int u,int ff,int depth,int p)
{
if(depth>=g[p])
{
if(depth==g[p]) ++cntg[p];
else {
if(!g[p]) bu[++tl]=p;
g[p]=depth, cntg[p]=1;
}
}
for(int i=hd[u];i;i=nex[i])
{
int v=to[i];
if(v==ff||vis[v]) continue;
dfs(v,u,depth+val[i],p+1);
}
}
void calc(int u)
{
int i,j,cur=0;
cntf[0]=1,tl=0;
for(i=hd[u];i;i=nex[i])
{
int v=to[i];
if(vis[v])
continue;
dfs(v,u,val[i],1);
for(j=cur+1;j<=tl;++j)
{
if(K-1<bu[j]) continue;
if(g[bu[j]]+f[K-bu[j]-1]==best)
{
answer+=(ll)(cntg[bu[j]]*cntf[K-bu[j]-1]);
}
else if(g[bu[j]]+f[K-bu[j]-1]>best)
{
best=g[bu[j]]+f[K-bu[j]-1];
answer=(ll)(cntg[bu[j]]*cntf[K-bu[j]-1]);
}
}
for(j=cur+1;j<=tl;++j)
{
if(g[bu[j]]==f[bu[j]]) cntf[bu[j]]+=cntg[bu[j]];
else if(g[bu[j]]>f[bu[j]])
{
cntf[bu[j]]=cntg[bu[j]];
f[bu[j]]=g[bu[j]];
}
}
for(j=cur+1;j<=tl;++j)
cntg[bu[j]]=g[bu[j]]=0;
cur=tl;
}
for(i=1;i<=cur;++i) cntf[bu[i]]=cntg[bu[i]]=f[bu[i]]=g[bu[i]]=0;
}
void solve(int u)
{
vis[u]=1;
calc(u);
for(int i=hd[u];i;i=nex[i])
if(!vis[to[i]])
sn=size[to[i]],root=0,getroot(to[i],u),solve(root);
}
int main()
{
root=0,mx[0]=inf,sn=n;
getroot(1,0),solve(root);
printf("%d %lld\n",best,answer);
return 0;
}
};
namespace Dijkstra
{
int d[N],done[N],vis[N];
struct Edge
{
int to,val;
Edge(int to=0,int val=0):to(to),val(val){}
};
bool cmp(Edge a,Edge b)
{
return a.to<b.to;
}
struct Node
{
int u,dis;
Node(int u=0,int dis=0):u(u),dis(dis){}
bool operator<(Node a)const
{
return a.dis<dis;
}
};
priority_queue<Node>q;
vector<Edge>G[N];
void add(int u,int v,int c)
{
G[u].push_back(Edge(v,c));
}
void dfs(int u)
{
vis[u]=1;
for(int i=0;i<G[u].size();++i)
if(!vis[G[u][i].to]&&d[u]+G[u][i].val==d[G[u][i].to])
{
vis[G[u][i].to]=1;
tree::addedge(u,G[u][i].to,G[u][i].val);
tree::addedge(G[u][i].to,u,G[u][i].val);
dfs(G[u][i].to);
}
}
void build_tree()
{
int i;
for(i=0;i<=n;++i) d[i]=inf;
q.push(Node(1,0)), d[1]=0;
while(!q.empty())
{
Node e=q.top();q.pop();
int u=e.u;
if(done[u]) continue;
done[u]=1;
for(i=0;i<G[u].size();++i)
{
Edge h=G[u][i];
if(d[h.to]>d[u]+h.val)
{
d[h.to]=d[u]+h.val;
q.push(Node(h.to,d[h.to]));
}
}
}
for(i=1;i<=n;++i) sort(G[i].begin(),G[i].end(),cmp);
dfs(1);
}
};
int main()
{
int i,j;
// setIO("input");
scanf("%d%d%d",&n,&m,&K);
for(i=1;i<=m;++i)
{
int a,b,c;
scanf("%d%d%d",&a,&b,&c);
Dijkstra::add(a,b,c);
Dijkstra::add(b,a,c);
}
Dijkstra::build_tree();
tree::main();
return 0;
}
luogu 2993 [FJOI2014]最短路径树问题 Dijkstra+点分治的更多相关文章
- [BZOJ4016][FJOI2014]最短路径树问题(dijkstra+点分治)
4016: [FJOI2014]最短路径树问题 Time Limit: 5 Sec Memory Limit: 512 MBSubmit: 1796 Solved: 625[Submit][Sta ...
- 【BZOJ4016】[FJOI2014]最短路径树问题(点分治,最短路)
[BZOJ4016][FJOI2014]最短路径树问题(点分治,最短路) 题面 BZOJ 洛谷 题解 首先把最短路径树给构建出来,然后直接点分治就行了. 这个东西似乎也可以长链剖分,然而没有必要. # ...
- 【BZOJ-4016】最短路径树问题 Dijkstra + 点分治
4016: [FJOI2014]最短路径树问题 Time Limit: 5 Sec Memory Limit: 512 MBSubmit: 1092 Solved: 383[Submit][Sta ...
- BZOJ 4016 [FJOI2014]最短路径树问题 (贪心+点分治)
题目大意:略 传送门 硬是把两个题拼到了一起= = $dijkstra$搜出单源最短路,然后$dfs$建树,如果$dis_{v}=dis_{u}+e.val$,说明这条边在最短路图内,然后像$NOIP ...
- 【bzoj4016】[FJOI2014]最短路径树问题 堆优化Dijkstra+DFS树+树的点分治
题目描述 给一个包含n个点,m条边的无向连通图.从顶点1出发,往其余所有点分别走一次并返回. 往某一个点走时,选择总长度最短的路径走.若有多条长度最短的路径,则选择经过的顶点序列字典序最小的那条路径( ...
- [BZOJ4016][FJOI2014]最短路径树问题
[BZOJ4016][FJOI2014]最短路径树问题 试题描述 给一个包含n个点,m条边的无向连通图.从顶点1出发,往其余所有点分别走一次并返回. 往某一个点走时,选择总长度最短的路径走.若有多条长 ...
- 【BZOJ4016】[FJOI2014]最短路径树问题
[BZOJ4016][FJOI2014]最短路径树问题 题面 bzoj 洛谷 题解 虽然调了蛮久,但是思路还是蛮简单的2333 把最短路径树构出来,然后点分治就好啦 ps:如果树构萎了,这组数据可以卡 ...
- [FJOI2014]最短路径树问题 长链剖分
[FJOI2014]最短路径树问题 LG传送门 B站传送门 长链剖分练手好题. 如果你还不会长链剖分的基本操作,可以看看我的总结. 这题本来出的很没水平,就是dijkstra(反正我是不用SPFA)的 ...
- 【BZOJ4016】[FJOI2014]最短路径树问题 最短路径树+点分治
[BZOJ4016][FJOI2014]最短路径树问题 Description 给一个包含n个点,m条边的无向连通图.从顶点1出发,往其余所有点分别走一次并返回. 往某一个点走时,选择总长度最短的路径 ...
随机推荐
- 利用微信web开发者工具调试企业微信页面
1.只有企业号的管理员才能调试. 2.勾选企业号的开发者工具(具体位置见下图,这个入口位置总是在变,一般来说,找到”微工作台“就能找到了) 3.下载web开发者工具 https://developer ...
- 【0.3】mysql复制的日常管理维护,mysql复制常见问题处理
[1]复制的日常管理 #复制的日常管理与维护 [1.1]show slave status\G :在从库查看从库线程状态 [1.2]flush tables with read lock; :主从不 ...
- 使用javascript完成一个简单工厂设计模式。
在JS中创建对象会习惯的使用new关键字和类构造函数(也是可以用对象字面量). 工厂模式就是一种有助于消除两个类依赖性的模式. 工厂模式分为简单工厂模式和复杂工厂模式,这篇主要讲简单工厂模式. 简单工 ...
- 区间最值的优秀数据结构---ST表
ST表,听起来高大上,实际上限制非常多,仅仅可以求最值问题: 为什么?先从原理看起: st表运用了倍增的思想:st[i][j] = min(st[i][j - 1],st[i + 2^(j - 1)) ...
- EBS自动行号,行金额自动汇总到头,金额根据币种编号总结
一.自动行号实现 1.方法一: 只需要将“序号”定义成公式,并将公式设置为:get_block_property('block_name',current_record)就可以实现了,或者把这行语句放 ...
- windows下搭建spark+python 开发环境
有时候我们会在windows 下开发spark程序,测试程序运行情况,再部署到真实服务器中运行. 那么本文介绍如何在windows 环境中搭建简单的基于hadoop 的spark 环境. 我的wind ...
- Qt表格导出图片
概述:qt中把某个控件导出保存为图片导出并不复杂,网上也有一堆方法.但是对于tableview中数据很多的情况下势必会出现滚动条,用传统的截屏抓图势会有滚动条,图片数据展示不全.在这我使用了一种折中方 ...
- TCP/IP模型层次结构
计算机网络体系结构 (1)OSI七层协议:从上到下:应用层.表示层.会话层.传输层.网络层.数据链路层.物理层. (2)TCP/IP四层协议:从上到下:应用层,传输层.网络层.数据链路层.网络接口层. ...
- fiddler抓包小技巧之自动保存抓包数据(可根据需求过滤)
首先 选择 如果有别的提示的话,你就按着提示走,就会安装一个编辑器,叫Fiddler Script. 正常情况下,你按着上面操作之后就会出现如下界面: 完事了之后,按下Ctrl+F来查找OnBefor ...
- JS常用函数原理的实现
本文针对目前常见的面试题,实现了相应方法的核心原理,部分边界细节未处理.后续也会持续更新,希望对你有所帮助. 1.实现一个call函数 // 思路:将要改变this指向的方法挂到目标this上执行并返 ...