洛谷 [FJOI2014]最短路径树问题 解题报告
[FJOI2014]最短路径树问题
题目描述
给一个包含\(n\)个点,\(m\)条边的无向连通图。从顶点\(1\)出发,往其余所有点分别走一次并返回。
往某一个点走时,选择总长度最短的路径走。若有多条长度最短的路径,则选择经过的顶点序列字典序最小的那条路径(如路径\(A\)为\(1,32,11\),路径\(B\)为\(1,3,2,11\),路径\(B\)字典序较小。注意是序列的字典序的最小,而非路径中节点编号相连的字符串字典序最小)。到达该点后按原路返回,然后往其他点走,直到所有点都走过。
可以知道,经过的边会构成一棵最短路径树。请问,在这棵最短路径树上,最长的包含\(K\)个点的简单路径长度为多长?长度为该最长长度的不同路径有多少条?
这里的简单路径是指:对于一个点最多只经过一次的路径。不同路径是指路径两端端点至少有一个不同,点\(A\)到点\(B\)的路径和点\(B\)到点\(A\)视为同一条路径。
输入输出格式
输入格式:
第一行输入三个正整数\(n\),\(m\),\(K\),表示有\(n\)个点\(m\)条边,要求的路径需要经过\(K\)个点。
接下来输入\(m\)行,每行三个正整数\(A_i,B_i,C_i(1\le A_i,B_i\le n,1 \le C_i\le10000)\),表示\(A_i\)和\(B_i\)间有一条长度为\(C_i\)的边。
数据保证输入的是连通的无向图。
输出格式:
输出一行两个整数,以一个空格隔开,第一个整数表示包含\(K\)个点的路径最长为多长,第二个整数表示这样的不同的最长路径有多少条。
说明
对于所有数据\(n\le30000,m\le60000\),\(2\le K\le n\)。
数据保证最短路径树上至少存在一条长度为K的路径。
Solution
第二自然段的题意我现在都没弄懂。
用我的理解就是先保证最短路,然后保证连边的编号的字典序是最小的。
这个可以先把最短路图跑出来,然后对每个点的出边排序,从\(1\)开始跑\(DFS\),边跑边连边。
然后就是淀粉质了。
吐槽题意+强行拼题+写起来不爽(不是为了了解一下最短路树我才不写呢)
复杂度\(O(nlogn)\)
Code:
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <queue>
const int N=3e4+10;
struct Edge
{
int v,w;
bool friend operator <(Edge n1,Edge n2){return n1.v<n2.v;}
}t;
std::vector <Edge> e[N],e0[N];
int n,m,k;
const int inf=0x3f3f3f3f;
#define P std::pair <int,int>
std::priority_queue <P,std::vector <P >,std::greater <P> > q;
int dis[N],used[N];
int head[N],to[N<<1],edge[N<<1],Next[N<<1],cnt;
void add(int u,int v,int w)
{
to[++cnt]=v,Next[cnt]=head[u],edge[cnt]=w,head[u]=cnt;
}
void disj()
{
memset(dis,0x3f,sizeof(dis));
q.push(std::make_pair(dis[1]=0,1));
while(!q.empty())
{
int u=q.top().second;
q.pop();
if(used[u]) continue;
used[u]=1;
for(int i=0;i<e[u].size();i++)
{
int v=e[u][i].v,w=e[u][i].w;
if(dis[v]>dis[u]+w)
{
dis[v]=dis[u]+w;
q.push(std::make_pair(dis[v],v));
}
}
}
memset(used,0,sizeof(used));
}
void dfsbuild(int now)
{
used[now]=1;
for(int i=0;i<e0[now].size();i++)
{
int v=e0[now][i].v,w=e0[now][i].w;
if(!used[v])
{
add(now,v,w);
add(v,now,w);
dfsbuild(v);
}
}
}
void build()
{
for(int u=1;u<=n;u++)
{
for(int i=0;i<e[u].size();i++)
{
int v=e[u][i].v,w=e[u][i].w;
if(dis[v]==dis[u]+w)
t={v,w},e0[u].push_back(t);
}
std::sort(e0[u].begin(),e0[u].end());
}
dfsbuild(1);
}
int ans,siz[N],rt,mi,mxlen[N],mx,del[N],td[N],tmxlen[N],scnt[N],tcnt[N];
int max(int x,int y){return x>y?x:y;}
void dfsroot(int now,int fa,int sz)
{
siz[now]=1;
int mx0=0;
for(int i=head[now];i;i=Next[i])
{
int v=to[i];
if(v==fa||del[v]) continue;
dfsroot(v,now,sz);
mx0=max(mx0,siz[v]);
siz[now]+=siz[v];
}
mx0=max(mx0,sz-siz[now]);
if(mx0<mi) mi=mx0,rt=now;
}
void dfs(int now,int fa,int dis,int dep)
{
if(dep>k) return;
if(mx<dis+mxlen[k-dep])
{
mx=dis+mxlen[k-dep];
ans=scnt[k-dep];
}
else if(mx==dis+mxlen[k-dep])
ans+=scnt[k-dep];
for(int i=head[now];i;i=Next[i])
{
int v=to[i];
if(v==fa||del[v]) continue;
dfs(v,now,dis+edge[i],dep+1);
}
if(tmxlen[dep]<dis)
{
tmxlen[dep]=dis;
tcnt[dep]=1;
}
else if(tmxlen[dep]==dis)
tcnt[dep]++;
}
void dfz(int now,int sz)
{
mi=1<<30;
dfsroot(now,0,sz);
now=rt;
del[now]=1;
for(int i=head[now];i;i=Next[i])
{
int v=to[i];
if(del[v]) continue;
dfs(v,now,edge[i],1);
for(int j=1;tmxlen[j]!=-inf;j++)
{
if(tmxlen[j]>mxlen[j])
{
scnt[j]=tcnt[j];
mxlen[j]=tmxlen[j];
}
else if(tmxlen[j]==mxlen[j])
scnt[j]+=tcnt[j];
tcnt[j]=0,tmxlen[j]=-inf;
}
}
if(mx<mxlen[k]) ans=scnt[k],mx=mxlen[k];
else if(mx==mxlen[k]) ans+=scnt[k];
for(int i=1;mxlen[i]!=-inf;i++) mxlen[i]=-inf;
for(int i=head[now];i;i=Next[i])
if(!del[to[i]])
dfz(to[i],siz[to[i]]);
}
int main()
{
//freopen("data.in","r",stdin);
//freopen("wr.out","w",stdout);
scanf("%d%d%d",&n,&m,&k);
for(int u,v,w,i=1;i<=m;i++)
{
scanf("%d%d%d",&u,&v,&w);
t={v,w};
e[u].push_back(t);
t={u,w};
e[v].push_back(t);
}
disj();
build();
--k;
for(int i=0;i<=k+1;i++)
tmxlen[i]=mxlen[i]=-inf;
dfz(1,n);
printf("%d %d\n",mx,ans);
return 0;
}
2018.10.22
洛谷 [FJOI2014]最短路径树问题 解题报告的更多相关文章
- 洛谷_Cx的故事_解题报告_第四题70
1.并查集求最小生成树 Code: #include <stdio.h> #include <stdlib.h> struct node { long x,y,c; ...
- 洛谷 P2317 [HNOI2005]星际贸易 解题报告
P2317 [HNOI2005]星际贸易 题目描述 输入输出格式 输入格式: 输出格式: 如果可以找到这样的方案,那么输出文件output.txt中包含两个整数X和Y.X表示贸易额,Y表示净利润并且两 ...
- 洛谷 P3802 小魔女帕琪 解题报告
P3802 小魔女帕琪 题目背景 从前有一个聪明的小魔女帕琪,兴趣是狩猎吸血鬼. 帕琪能熟练使用七种属性(金.木.水.火.土.日.月)的魔法,除了能使用这么多种属性魔法外,她还能将两种以上属性组合,从 ...
- 洛谷 P2606 [ZJOI2010]排列计数 解题报告
P2606 [ZJOI2010]排列计数 题目描述 称一个\(1,2,...,N\)的排列\(P_1,P_2...,P_n\)是\(Magic\)的,当且仅当对所以的\(2<=i<=N\) ...
- 洛谷1303 A*B Problem 解题报告
洛谷1303 A*B Problem 本题地址:http://www.luogu.org/problem/show?pid=1303 题目描述 求两数的积. 输入输出格式 输入格式: 两个数 输出格式 ...
- 洛谷 P3398 仓鼠找sugar 解题报告
P3398 仓鼠找sugar 题目描述 小仓鼠的和他的基(mei)友(zi)sugar住在地下洞穴中,每个节点的编号为1~n.地下洞穴是一个树形结构.这一天小仓鼠打算从从他的卧室(a)到餐厅(b),而 ...
- 洛谷 P3084 [USACO13OPEN]照片Photo 解题报告
[USACO13OPEN]照片Photo 题目描述 农夫约翰决定给站在一条线上的\(N(1 \le N \le 200,000)\)头奶牛制作一张全家福照片,\(N\)头奶牛编号\(1\)到\(N\) ...
- NOIP2015 D2T3 洛谷2680 BZOJ4326 运输计划 解题报告
前言:个人认为这是历年NOIP中比较简单的最后一题了,因此将自己的思路与大家分享. 题目大意: 给一棵无根树,给出m条路径.允许将树上的一条边的权值改为0.求m条路径长度最大值的最小值.n,m< ...
- 洛谷 P3962 [TJOI2013]数字根 解题报告
P3962 [TJOI2013]数字根 题意 数字根:这个数字每一位的数字加起来求和,反复这个过程直到和小于10. 给出序列\(a\),询问区间\([l,r]\)连续的子区间里最大前5个不同的数字根, ...
随机推荐
- tp5 数据库信息导出到excel(带图片)
function excel_down(){ //导入谁就去查谁 $data=Db::name('order_xueyou')->select(); // 导出Exl // import(&qu ...
- powerpoint教程资料,PPT的
Powerpoint,是微软公司设计的演示文稿软件,利用Powerpoint不仅可以创建演示文稿,还可以在互联网上召开面对面会议.远程会议或在网上给观众展示演示文稿,掌握利用PowerPoint是一项 ...
- C语言的结构体,枚举类型在程序中的作用
http://www.xue63.com/xueask-1221-12212854.html 结构和枚举类型从程序实现的角度来说,是用更接近自然语言的方式来表达数据.比如说实现2维空间的点,你可以使用 ...
- (数据科学学习手札06)Python在数据框操作上的总结(初级篇)
数据框(Dataframe)作为一种十分标准的数据结构,是数据分析中最常用的数据结构,在Python和R中各有对数据框的不同定义和操作. Python 本文涉及Python数据框,为了更好的视觉效果, ...
- 为什么我要放弃javaScript数据结构与算法(第三章)—— 栈
有两种结构类似于数组,但在添加和删除元素时更加可控,它们就是栈和队列. 第三章 栈 栈数据结构 栈是一种遵循后进先出(LIFO)原则的有序集合.新添加的或待删除的元素都保存在栈的同一端,称为栈顶,另一 ...
- ansible结合SHELL搭建自己的CD持续交付系统
一. 设计出发点 因公司业务面临频繁的迭代上线,一日数次.仅仅依靠手工效率过低且易出错. 考虑搭建一套可以满足现有场景的上线系统. 二 .为何采用ansible+shell方式 1.可控性(完全自主拥 ...
- python pip ,安装,卸载,查看等命令,不同版本
pycharm及python的使用说明 Python和 pycharm的使用 1. pycharm和Python 下载 安装后需要激活码.判断Python是否安装好了,cmd下跑: python ...
- 分支push不上去的问题
还原一下现场,我在自己的项目里面,从master里面checkout的一个分支,当我在我这个分支里面进行 push代码的操作,我突然发现我的代码不能执行push的操作,如图 这个原因是由于远端的仓库没 ...
- 6 wireshark 安装使用 数据包抓取
1.wireshark安装 2.开始使用 3.界面详情 4. 数据包抓取 5.过滤数据
- ORB-SLAM (四)tracking单目初始化
单目初始化以及通过三角化恢复出地图点 单目的初始化有专门的初始化器,只有连续的两帧特征点均>100个才能够成功构建初始化器. ); 若成功获取满足特征点匹配条件的连续两帧,并行计算分解基础矩阵和 ...