挺简单的,但是给人一种把两个问题强行弄到一起的感觉.

十分不好写.

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+点分治的更多相关文章

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

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

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

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

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

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

  4. BZOJ 4016 [FJOI2014]最短路径树问题 (贪心+点分治)

    题目大意:略 传送门 硬是把两个题拼到了一起= = $dijkstra$搜出单源最短路,然后$dfs$建树,如果$dis_{v}=dis_{u}+e.val$,说明这条边在最短路图内,然后像$NOIP ...

  5. 【bzoj4016】[FJOI2014]最短路径树问题 堆优化Dijkstra+DFS树+树的点分治

    题目描述 给一个包含n个点,m条边的无向连通图.从顶点1出发,往其余所有点分别走一次并返回. 往某一个点走时,选择总长度最短的路径走.若有多条长度最短的路径,则选择经过的顶点序列字典序最小的那条路径( ...

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

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

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

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

  8. [FJOI2014]最短路径树问题 长链剖分

    [FJOI2014]最短路径树问题 LG传送门 B站传送门 长链剖分练手好题. 如果你还不会长链剖分的基本操作,可以看看我的总结. 这题本来出的很没水平,就是dijkstra(反正我是不用SPFA)的 ...

  9. 【BZOJ4016】[FJOI2014]最短路径树问题 最短路径树+点分治

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

随机推荐

  1. python list pop()方法

    #pop()用于移除列表中的一个元素(默认是最后一个元素,并且返回该元素的值) list1=['Google','Runoob','Taobao'] list_pop=list1.pop() prin ...

  2. 集合运算 - Java实现集合的交、并、差

    1.使用java的Set实现集合的交.并.差 package com.lfy.Set; import java.util.HashSet; import java.util.Set; /** * 集合 ...

  3. Spring(十三)-- Spring 事务

    Spring 事务 1. 回忆之前事务知识点  一:事务的概念 将一系列的数据操作捆绑在一起,成为一个整体进行统一管理! 一条或者多条sql语句的集合!  二:事务的ACID特性 原子性(Atomic ...

  4. azkaban安装步骤

    安装包 1.得到软件包 azkaban-executor-server-2.5.0.tar.gz azkaban-sql-script-2.5.0.tar.gz azkaban-web-server- ...

  5. QQ登陆

    QQ第三方登陆调用接口实现 <?php $appid="101353491"; session_start(); $appkey="df4e46ba7da52f78 ...

  6. Codeforces 1196E. Connected Component on a Chessboard

    传送门 注意到棋盘可以看成无限大的,那么只要考虑如何构造一个尽可能合法的情况 不妨假设需要的白色格子比黑色格子少 那么容易发现最好的情况之一就是白色排一排然后中间黑的先连起来,剩下黑色的再全部填白色周 ...

  7. 将Abp的UnitTest中的InMemory改为SQLite in memory

    添加nuget包 Microsoft.EntityFrameworkCore.Sqlite 添加ServiceCollectionRegistrarSqlite public static class ...

  8. 常用的TCP/UDP端口

    已知的TCP/UDP端口可以在wikipedia上找到: List of TCP and UDP port numbers, 太多了,按组列举了最常用的,如下: FTP:21SSH:22Telnet: ...

  9. C#派生类的构造函数

    构造函数的调用顺序是先调用System.Object,再按照层次结构由上向下(基类=>派生类)进行,直到到达编译器要实例化的类为止.在此过程中,每个构造函数都初始化自己类中的字段.编译器先自下而 ...

  10. Qt表格导出图片

    概述:qt中把某个控件导出保存为图片导出并不复杂,网上也有一堆方法.但是对于tableview中数据很多的情况下势必会出现滚动条,用传统的截屏抓图势会有滚动条,图片数据展示不全.在这我使用了一种折中方 ...