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出发,往其余所有点分别走一次并返回. 往某一个点走时,选择总长度最短的路径 ...
随机推荐
- [转帖]IntelliJ IDEA 2018.3.3破解方法
IntelliJ IDEA 2018.3.3破解方法 https://blog.csdn.net/qq_42862882/article/details/86477495 验证了下 也可以激活. ...
- “automation服务器不能创建对象”的问题的解决方案大全
本人工作中的应用系统都是jsp的,大量javascript程序,一旦出“automation服务器不能创建对象”问题,大量报表及查询无法保存,苦思冥想.千尝万试,终于将其搞定,现将相关方案与大家共享. ...
- Mysql-Sqlalchemy-增删改查分组等操作
#!/usr/bin/env python # -*- coding:utf-8 -*- from sqlalchemy.ext.declarative import declarative_base ...
- 多进程-Pool进程池
from multiprocessing import Pool import os,time def Foo(i): time.sleep(2) print("in process&quo ...
- Java Web开发技术教程入门-JavaBean组件与Servlet
补更:阅战阅勇第7/8/9Days笔记 昨天我们了解了JDBC技术的一些日常操作,对于数据库而言,不仅仅的只有"增,删,改,查".博主觉得最重要的是SQL语句的优化,一个" ...
- cf 1163D Mysterious Code (字符串, dp)
大意: 给定字符串$C$, 只含小写字母和'*', '*'表示可以替换为任意小写字母, 再给定字符串$S,T$, 求$S$在$C$中出现次数-$T$在$C$中出现次数最大值. 设$dp[i][j][k ...
- leetcode难题
4 寻找两个有序数组的中位数 35.9% 困难 10 正则表达式匹配 24.6% 困难 23 合并K个排序链表 47.4% 困难 25 K ...
- idea-代码格式化快捷键设置(2019.1版)
idea默认格式化快捷键是:Ctrl+Alt+L,有时会因其它软件快捷键的冲突导致失灵. 设置方法如下: 1.File --> Settings... 2. Keymap -> Code ...
- 总线(bus)简介
内容来自于<Computer Organization>,这是我的一篇学习笔记
- 07-django项目连接远程mysql数据库
比如电脑a(ip地址为192.168.0.aaa)想要连接访问电脑b(ip地址为192.168.0.bbb)的数据库: 对电脑a(ip地址为192.168.0.aaa): 在项目settings.py ...