题目大意:略 传送门

硬是把两个题拼到了一起= =

$dijkstra$搜出单源最短路,然后$dfs$建树,如果$dis_{v}=dis_{u}+e.val$,说明这条边在最短路图内,然后像$NOIP2018 D2T1$那样的思路,贪心地选出当前节点的所有子节点里,未被访问过的编号最小的节点递归,回溯后重复此过程。可以用$vector$预处理出来,或者用堆= =。

然后就是很经典的点分治问题了

求出树上固定边数的最长链,类似于[IOI2011]Race这道题的思路,只不过是反着搞。每次选择一个重心为根,开个桶统计答案就行了

求固定长度链的个数。但这道题用桶可能会存不下,可以写$map$代替桶(不过数据里好像没有存不下的情况..)。

由于判定条件是二元的,一个是边数一个是长度,排序双指针不知道行不行

还有我把$vector$改成堆就过了是什么鬼

代码巨长巨恶心

 #include <map>
#include <queue>
#include <vector>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define N1 30010
#define M1 1010
#define ll long long
#define inf 233333333
#define it map<node,int>::iterator
using namespace std; int gint()
{
int ret=,fh=;char c=getchar();
while(c<''||c>''){if(c=='-')fh=-;c=getchar();}
while(c>=''&&c<=''){ret=ret*+c-'';c=getchar();}
return ret*fh;
}
int n,m,K;
struct Edge{
int to[N1<<],nxt[N1<<],val[N1<<],head[N1],cte;
void ae(int u,int v,int w)
{
cte++;to[cte]=v,val[cte]=w;
nxt[cte]=head[u],head[u]=cte;
}
}g,e;
namespace Build_Tree{
struct node{
int id,val;
friend bool operator < (const node &s1,const node &s2){
if(s1.val!=s2.val) return s1.val>s2.val;
return s1.id>s2.id;
}
};
int cmp(node s1,node s2){return s1.id<s2.id;}
int vis[N1],dis[N1];
void dijkstra()
{
memset(dis,0x3f,sizeof(dis));
priority_queue<node>q;
q.push((node){,}); dis[]=;
int j,u,v; node k;
while(!q.empty())
{
k=q.top(); q.pop(); u=k.id; if(vis[u]) continue; vis[u]=;
for(j=g.head[u];j;j=g.nxt[j])
{
v=g.to[j];
if(dis[v]>dis[u]+g.val[j])
dis[v]=dis[u]+g.val[j], q.push((node){v,dis[v]});
}
}
memset(vis,,sizeof(vis));
}
priority_queue<node>q[N1];
void dfs(int u)
{
vis[u]=; node k;
for(int j=g.head[u];j;j=g.nxt[j])
{
if(vis[g.to[j]]||dis[g.to[j]]!=dis[u]+g.val[j]) continue;
q[u].push((node){g.val[j],g.to[j]});
}
while(!q[u].empty())
{
k=q[u].top(); q[u].pop(); if(vis[k.val]) continue;
e.ae(u,k.val,k.id); e.ae(k.val,u,k.id);
dfs(k.val);
}
}
void Main()
{
dijkstra();
dfs();
}
};
int sz[N1],ms[N1],use[N1],tsz,G;
void gra(int u,int dad)
{
sz[u]=; ms[u]=;
for(int j=e.head[u];j;j=e.nxt[j])
{
if(use[e.to[j]]||e.to[j]==dad) continue;
gra(e.to[j],u);
sz[u]+=sz[e.to[j]]; ms[u]=max(ms[u],sz[e.to[j]]);
}
ms[u]=max(ms[u],tsz-sz[u]);
if(ms[u]<ms[G]) G=u;
} int ma[N1],q[N1],eq,tq[N1],et,dep[N1],dis[N1]; namespace Find_ma{
int ans;
void dfs(int u,int dad)
{
if(dep[u]>K) return; tq[++et]=u;
for(int j=e.head[u];j;j=e.nxt[j])
{
if(use[e.to[j]]||e.to[j]==dad) continue;
dep[e.to[j]]=dep[u]+; dis[e.to[j]]=dis[u]+e.val[j];
dfs(e.to[j],u);
}
}
void calc(int u)
{
int i,j,x;
dep[u]=; ma[]=;
for(j=e.head[u];j;j=e.nxt[j])
{
if(use[e.to[j]]) continue;
dep[e.to[j]]=; dis[e.to[j]]=e.val[j];
dfs(e.to[j],u);
for(i=;i<=et;i++)
{
x=tq[i];
ans=max(ans,ma[K-dep[x]]+dis[x]);
}
while(et)
{
x=tq[et--]; q[++eq]=dep[x];
ma[dep[x]]=max(ma[dep[x]],dis[x]);
}
}
while(eq) ma[q[eq--]]=-inf;
}
void main_dfs(int u)
{
int j,v; use[u]=; calc(u);
for(j=e.head[u];j;j=e.nxt[j])
{
v=e.to[j]; if(use[v]) continue;
tsz=sz[v]; G=; gra(v,u);
main_dfs(G);
}
}
void solve()
{
ms[]=tsz=n; G=; gra(,-); gra(G,-);
for(int i=;i<=n;i++) ma[i]=-inf;
main_dfs(G);
}
}; namespace Count{ struct node{
int dis,dep;
friend bool operator < (const node &s1,const node &s2)
{
if(s1.dis!=s2.dis) return s1.dis<s2.dis;
return s1.dep<s2.dep;
}
};
int M,ans; map<node,int>mp;
void dfs(int u,int dad)
{
if(dis[u]>M||dep[u]>K) return;
mp[(node){dis[u],dep[u]}]++;
for(int j=e.head[u];j;j=e.nxt[j])
{
if(use[e.to[j]]||e.to[j]==dad) continue;
dep[e.to[j]]=dep[u]+; dis[e.to[j]]=dis[u]+e.val[j];
dfs(e.to[j],u);
}
}
int calc(int u)
{
int ret=; node k,t; mp.clear(); dfs(u,-);
for(it i=mp.begin();i!=mp.end();i++)
{
k=i->first; t=(node){M-k.dis,K-k.dep};
if(mp.find(t)==mp.end()) continue;
if(k.dis==t.dis&&k.dep==t.dep) ret+=(i->second)*((i->second)-);
else ret+=mp[t]*(i->second);
}
return ret/;
}
void main_dfs(int u)
{
int j,v; use[u]=; dis[u]=; dep[u]=; ans+=calc(u);
for(j=e.head[u];j;j=e.nxt[j])
{
v=e.to[j]; if(use[v]) continue;
ans-=calc(v); tsz=sz[v]; G=; gra(v,u);
main_dfs(G);
}
}
void solve()
{
M=Find_ma::ans;
memset(use,,sizeof(use));
ms[]=tsz=n; G=; gra(,-); gra(G,-);
main_dfs(G);
}
}; int main()
{
//freopen("t2.in","r",stdin);
int i,x,y,z;
scanf("%d%d%d",&n,&m,&K); K--;
for(i=;i<=m;i++)
{
x=gint(),y=gint(),z=gint();
g.ae(x,y,z),g.ae(y,x,z);
}
Build_Tree::Main();
Find_ma::solve();
Count::solve();
printf("%d %d\n",Find_ma::ans,Count::ans);
return ;
}
/*
6 6 4
1 2 1
2 3 1
3 4 1
2 5 1
3 6 1
5 6 1 3 4 7 6 4
1 2 2
1 3 1
2 4 4
2 5 3
3 6 2
5 7 2 9 1
*/

BZOJ 4016 [FJOI2014]最短路径树问题 (贪心+点分治)的更多相关文章

  1. bzoj 4016 [FJOI2014]最短路径树问题(最短路径树+树分治)

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

  2. bzoj 4016: [FJOI2014]最短路径树问题

    bzoj4016 最短路路径问题 Time Limit: 5 Sec Memory Limit: 512 MB Description 给一个包含n个点,m条边的无向连通图.从顶点1出发,往其余所有点 ...

  3. BZOJ 4016: [FJOI2014]最短路径树问题( 最短路 + 点分治 )

    先跑出最短路的图, 然后对于每个点按照序号从小到大访问孩子, 就可以搞出符合题目的树了. 然后就是经典的点分治做法了. 时间复杂度O(M log N + N log N) -------------- ...

  4. [BZOJ4016][FJOI2014]最短路径树问题(dijkstra+点分治)

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

  5. 【BZOJ4016】[FJOI2014]最短路径树问题(点分治,最短路)

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

  6. luogu 2993 [FJOI2014]最短路径树问题 Dijkstra+点分治

    挺简单的,但是给人一种把两个问题强行弄到一起的感觉. 十分不好写. Code: #include <queue> #include <cstdio> #include < ...

  7. 【BZOJ-4016】最短路径树问题 Dijkstra + 点分治

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

  8. 【BZOJ4016】[FJOI2014]最短路径树问题

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

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

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

随机推荐

  1. [置顶] 来自 HeroKu 的 HTTP API 设计指南(中文版)

    转载:http://get.jobdeer.com/343.get 来自 HeroKu 的 HTTP API 设计指南(中文版) 翻译 by @Easy 简介 本指南中文翻译者为 @Easy ,他是国 ...

  2. PHP学习总结(10)——PHP入门篇之自定义网站根目录

  3. Cookie 工具类

    一.导入 jar 包 <dependency> <groupId>javax.servlet</groupId> <artifactId>servlet ...

  4. 参数化取值策略Unique

    Unique:主要是强调取值的唯一性,如果到最后没有该值了,LR提供了其他解决方案,如图所示: 此处的下拉列表中提供了三种方式,具体如下: About Vuser,当取值次数超过参数的行数时,忽略脚本 ...

  5. kfka学习笔记一:使用Python操作Kafka

    1.准备工作 使用python操作kafka目前比较常用的库是kafka-python库,但是在安装这个库的时候需要依赖setuptools库和six库,下面就要分别来下载这几个库 https://p ...

  6. itunes connect上传截图提示无法加载文件问题

    解决的方法: 图片名字中不能包括汉字,要英文字母或数字.

  7. SDUT OJ 1124 飞越原野 (三维BFS练习)

    飞跃原野 nid=24#time" title="C.C++.go.haskell.lua.pascal Time Limit5000ms Memory Limit 65536K ...

  8. linux虚拟机网络设置好ping百度没有用

    场景:公司内网,本机使用的是本地连接,不是wiff,虚拟机设置了桥接模式 问题:使用桥接模式 启动好网络服务,查看ifconfig也获取到了设置的ip,可是ping了www.baidu.com还是没有 ...

  9. spring batch(二):核心部分(1):配置Spring batch

    spring batch(二):核心部分(1):配置Spring batch 博客分类: Spring 经验 java   chapter 3.Batch configuration 1.spring ...

  10. webview同步cookies

    目前很多android app都内置了可以显示web页面的界面,会发现这个界面一般都是由一个叫做WebView的组件渲染出来的,学习该组件可以为你的app开发提升扩展性. 先说下WebView的一些优 ...