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出发,往其余所有点分别走一次并返回. 往某一个点走时,选择总长度最短的路径 ...
随机推荐
- Redhat更换Centos源
redhat默认自带的yum源需要注册,才能更新,报错: This system is not registered to Red Hat Subscription Management. You c ...
- 【0.3】mysql复制的日常管理维护,mysql复制常见问题处理
[1]复制的日常管理 #复制的日常管理与维护 [1.1]show slave status\G :在从库查看从库线程状态 [1.2]flush tables with read lock; :主从不 ...
- (5.5)mysql高可用系列——MySQL半同步复制(实践)
关键词,mysql半同步复制 [0]实验环境 操作系统:CentOS linux 7.5 数据库版本:5.7.24 数据库架构:主从复制,主库用于生产,从库用于数据容灾和主库备机,采用默认传统的异步复 ...
- FFmpeg4.0笔记:封装ffmpeg的视频帧转换功能类CSws
Github https://github.com/gongluck/FFmpeg4.0-study/tree/master/Cff CSws.h /************************* ...
- # Pycharm打造高效Python IDE
Pycharm打造高效Python IDE 建议以scientific mode运行,在科学计算时,可以方便追踪变量变化,并且会提示函数的用法,比普通模式下的提示更加智能,一般在文件中引入了numpy ...
- ftp服务器上传下载共享文件
1 windows下搭建ftp服务器 https://blog.csdn.net/qq_34610293/article/details/79210539 搭建好之后浏览器输入 ftp://ip就可以 ...
- sql server SQL 服务器 - RDBMS
SQL 服务器 - RDBMS --现代的 SQL 服务器构建在 RDBMS 之上. DBMS - 数据库管理系统(Database Management System) --数据库管理系统是一种可以 ...
- IDEA导入Eclipse 非Maven的Web项目
- python:enumerate 函数
说明 enumerate()是python的内置函数: 对于一个可迭代的(iterable)/可遍历的对象(如列表.字符串),enumerate将其组成一个索引序列,利用它可以同时获得索引和值 多用于 ...
- 不基于比较的排序算法:Counting-sort和Radix-sort