这道题还是非常简单的,由于我们要保证最小字典序,因此我们需要把边进行排序,然后从大到小插入,因为链式前向星是倒着存的。我们只需要先跑一个最短路,然后查询边是不是在最短路上,这个可以通过枚举边并用

dist[v]=dist[u]+edge[i]判断即可,如果是的话我们在这个边上打上标记。并进行一次DFS打上标记,保证是一颗树。

然后就简单了,直接点分治查询子树链的长度和节点个树。然后就很更新保存即可,这个查询其实和上个题很相似,用一个mp保存点的个数对应的最长的链,这样就能在枚举子树的链的节点个数的时候,查询是否有其他子树的节点个数,和当前节点的链组成一条合法的链。

。。。为毛找重心在外面开一个maxlink,维护内部最长链会错。。。开数组维护每个节点就不会。。。真奇怪。。。

#include<iostream>
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<queue>
#include<vector>
#define pii pair<int,int>
using namespace std;
const int INF = 0x3f3f3f3f;
const int maxx = 2e5+6;
struct edge{
int v,w,next,use;
}e[maxx];
int tot,root,n,m,k,l,r,size,ans,ans1;
int sz[maxx],vis[maxx],head[maxx],dis[maxx],id[maxx],q[maxx];
int d[maxx],mp[maxx],cnt[maxx],mx[maxx];
struct node{
int u,v,w;
}edge[maxx];
struct que{
int len,k;
}que[maxx];
void add(int x,int y,int z){
e[++tot].v=y;e[tot].w=z;e[tot].next=head[x];head[x]=tot;
e[++tot].v=x;e[tot].w=z;e[tot].next=head[y];head[y]=tot;
}
void dfs(int x){
vis[x]=1;
for (int i=head[x];i;i=e[i].next){
int v=e[i].v;
if (e[i].use==1 && !vis[v]){
e[i].use=e[i^1].use=2;
dfs(v);
}
}
}
void dji(){
priority_queue<pii>q;
for (int i=1;i<=n;i++){
dis[i]=INF;
}
dis[1]=0;
q.push(make_pair(0,1));
while(q.size()){
int u=q.top().second;
q.pop();
if (vis[u])continue;
vis[u]=1;
for (int i=head[u];i;i=e[i].next){
int v=e[i].v;
if (dis[v]>dis[u]+e[i].w){
dis[v]=dis[u]+e[i].w;
q.push(make_pair(-dis[v],v));
}
}
}
for (int i=2;i<=tot;i++){
int u=e[i^1].v;
int v=e[i].v;
if (dis[v]==dis[u]+e[i].w){
e[i].use=1;
}
}
memset(vis,0,sizeof(vis));
dfs(1);
}
void getroot(int x,int fa)
{
sz[x]=1;mx[x]=0;
for (int i=head[x];i;i=e[i].next)
{
if (e[i].use<2||vis[e[i].v]||e[i].v==fa) continue;
getroot(e[i].v,x);
sz[x]+=sz[e[i].v];
mx[x]=max(mx[x],sz[e[i].v]);
}
mx[x]=max(mx[x],size-sz[x]);
if (!root||mx[x]<mx[root]) root=x;
}
void getdis(int u,int num,int dist,int fa)
{
//cout<<u<<"orz"<<num<<endl;
if (num<=k)que[++r].k=num,que[r].len=dist;
for (int i=head[u];i;i=e[i].next)
{
int v=e[i].v;
// cout<<v<<" "<<e[i].use<<" "<<vis[v]<<" "<<fa<<" "<<num<<endl;
if (e[i].use<2 || vis[v] || v==fa)continue;
getdis(v,num+1,dist+e[i].w,u);
}
}
void slove(int u){
vis[u]=1;
r=0;
for (int i=head[u];i;i=e[i].next)
{
int v=e[i].v;
if (e[i].use<2||vis[v])continue;
int tmp=r;
getdis(v,1,e[i].w,u);
for (int j=tmp+1;j<=r;j++)
{
int dist=que[j].len;
int num=que[j].k;
if (mp[k-num]>-1)
{
if (dist+mp[k-num]>ans)ans=dist+mp[k-num],ans1=cnt[k-num];
else if (dist+mp[k-num]==ans)ans1+=cnt[k-num];
}
}
for (int j=tmp+1;j<=r;j++)
{
int num=que[j].k,dist=que[j].len;
if (dist>mp[num])mp[num]=dist,cnt[num]=1;
else if (dist==mp[num])cnt[num]++;
}
}
while(r)mp[que[r].k]=-1,cnt[que[r].k]=0,r--;
for (int i=head[u];i;i=e[i].next)
{
int v=e[i].v;
if (e[i].use<2||vis[v])continue;
root=0;
size=sz[v];
getroot(v,u);
slove(root);
}
}
bool cmp(node a,node b){
if (a.u==b.u){
if (a.v==b.v){
return a.w<b.w;
}
return a.v<b.v;
}
return a.u<b.u;
}
int main(){
scanf("%d%d%d",&n,&m,&k);
k--;
for (int i=1;i<=m;i++){
scanf("%d%d%d",&edge[i].u,&edge[i].v,&edge[i].w);
}
sort(edge+1,edge+1+m,cmp);
tot=1;
memset(cnt,0,sizeof(cnt));
memset(head,0,sizeof(head));
for (int i=m;i>=1;i--){
add(edge[i].u,edge[i].v,edge[i].w);
}
dji();
memset(vis,0,sizeof(vis));
root=0;
size=n;
getroot(1,0);
for (int i=1;i<=k;i++)mp[i]=-1;
cnt[0]=1;
slove(root);
printf("%d %d\n",ans,ans1);
return 0;
}

  

P2993 [FJOI2014]最短路径树问题 点分治+最短路的更多相关文章

  1. Bzoj4016/洛谷P2993 [FJOI2014] 最短路径树问题(最短路径问题+长链剖分/点分治)

    题面 Bzoj 洛谷 题解 首先把最短路径树建出来(用\(Dijkstra\),没试过\(SPFA\)\(\leftarrow\)它死了),然后问题就变成了一个关于深度的问题,可以用长链剖分做,所以我 ...

  2. P2993 [FJOI2014]最短路径树问题

    思路:最短路+点分治 提交:2次 错因:更新桶的时候没有重置,而直接加上了. 题解: 对于构建最短路树,我们可以先跑最短路,然后dfs一遍连边. 然后就是点分治了,还是一些桶,存点数为\(x\)的最长 ...

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

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

  4. BZOJ_4016_[FJOI2014]最短路径树问题_最短路+点分治

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

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

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

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

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

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

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

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

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

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

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

随机推荐

  1. nginx链接末尾自动补全斜杠

    放在locaation里边就行 if (-d $request_filename){ rewrite ^(.*[^/])$ $/ permanent;#加斜杠 } 这样,nginx就会进行判断了,如果 ...

  2. ucore 物理内存探测 lab2 附录A&B

    探测物理内存分布的大小和方法 bootloader 增加的工作 bootasm.S 中对应了 probe_memory 到 finish_probe 的部分. 通过BIOS 中断 获取内存可调用参数为 ...

  3. makefile 语法笔记 3

    这里说明了 在一些情况下 这也是可以使用通配符的 objects =*.o 这种情况是不会展开的 makefile 中的变量是C++/C 中的宏 如果希望展开,可以使用 $(wildcard *.o) ...

  4. Java 8最快的垃圾收集器是什么?

    OpenJDK 8 有多种 GC(Garbage Collector)算法,如 Parallel GC.CMS 和 G1.哪一个才是最快的呢?如果在 Java 9 中将 Java 8 默认的 GC 从 ...

  5. 2019-4-16-C#-在-8.0-对比-string-和-string_-的类型

    title author date CreateTime categories C# 在 8.0 对比 string 和 string? 的类型 lindexi 2019-04-16 10:16:56 ...

  6. NOIP模拟 9.09

    AK300分 果实计数 (count.pas/.c/.cpp) 时间限制:1s,空间限制32MB 题目描述: 淘淘家有棵奇怪的苹果树,这棵树共有n+1层,标号为0~n.这棵树第0层只有一个节点,为根节 ...

  7. 【CodeVS】【2004年NOIP全国联赛提高组】1057 津津的储蓄计划

    1057 津津的储蓄计划 2004年NOIP全国联赛提高组 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 青铜 Bronze 题目描述 Description 津津的零花钱一直都是 ...

  8. Linux硬链接和软连接

    硬链接(hard link): A是B的硬链接(A和B都是文件名),则A的目录项中的inode节点号与B的目录项中的inode节点号相同,即一个inode节点对应两个不同的文件名,两个文件名指向同一个 ...

  9. 遇到的bug

    1  div出现莫名其妙的空白bug 之前写了一个后台管理系统,项目不小加上是改版,很多的js都是用的之前的,  bug多到自己都不想看, 其中有个是用iframe 框架加载表格页面,但是右边跟下边出 ...

  10. kubernetes1.4新特性:增加新的节点健康状况类型DiskPressure

    背景资料 在Kubernetes架构图中可以看到,节点(Node)是一个由管理节点委托运行任务的worker. 它能运行一个或多个Pods,节点(Node)提供了运行容器环境所需要的所有必要条件,在K ...