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

Time Limit: 5 Sec  Memory Limit: 512 MB
Submit: 426  Solved: 147
[Submit][Status][Discuss]

Description

给一个包含n个点,m条边的无向连通图。从顶点1出发,往其余所有点分别走一次并返回。
往某一个点走时,选择总长度最短的路径走。若有多条长度最短的路径,则选择经过的顶点序列字典序最小的那条路径(如路径A为1,32,11,路
径B为1,3,2,11,路径B字典序较小。注意是序列的字典序的最小,而非路径中节点编号相连的字符串字典序最小)。到达该点后按原路返回,然后往其他
点走,直到所有点都走过。
可以知道,经过的边会构成一棵最短路径树。请问,在这棵最短路径树上,最长的包含K个点的简单路径长度为多长?长度为该最长长度的不同路径有多少条?
这里的简单路径是指:对于一个点最多只经过一次的路径。不同路径是指路径两端端点至少有一个不同,点A到点B的路径和点B到点A视为同一条路径。

Input

第一行输入三个正整数n,m,K,表示有
n个点m条边,要求的路径需要经过K个点。接下来输入m行,每行三个正整数Ai,Bi,Ci(1<=Ai,Bi<=n,1<=Ci&
lt;=10000),表示Ai和Bi间有一条长度为Ci的边。数据保证输入的是连通的无向图。
 
 

Output

输出一行两个整数,以一个空格隔开,第一个整数表示包含K个点的路径最长为多长,第二个整数表示这样的不同的最长路径有多少条。
 

Sample Input

6 6 4
1 2 1
2 3 1
3 4 1
2 5 1
3 6 1
5 6 1

Sample Output

3 4

HINT

对于所有数据n<=30000,m<=60000,2<=K<=n。数据保证最短路径树上至少存在一条长度为K的路径。

【思路】

先求出满足要求的最短路树来。

分治:求出过根节点的点对数,其它递归处理。

求过根节点的点对:假设现在处理根节点的S子树,用f[i][0]表示前S-1棵子树中与根相距i个节点(不含根)的最长路径,f[i][1]表示方案数,类似的定义tmp为当前S子树的统计结果。一遍bfs构造出tmp,枚举该子树上的结点数更新答案,然后用tmp更新f。

需要注意的有:

累计答案的诸多小细节。

f[][],tmp[][],queue的清零。

【代码】

 #include<cstdio>
#include<vector>
#include<queue>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std; const int N = +;
const int INF = 1e9+1e9; struct Edge {
int v,w;
Edge(int v=,int w=):v(v),w(w) {}
bool operator < (const Edge& rhs) const {
return v<rhs.v;
}
};
queue<int> q;
int n,m,K,root,size,d[N],inq[N];
int ans1,ans2,siz[N],mx[N],vis[N],dep[N],dis[N],fa[N];
vector<Edge> g[N],G[N]; void spfa() {
for(int i=;i<=n;i++) d[i]=INF;
memset(inq,,sizeof(inq));
inq[]=; q.push();
while(!q.empty()) {
int u=q.front(); q.pop(); inq[u]=;
for(int i=;i<g[u].size();i++) {
int v=g[u][i].v,w=g[u][i].w;
if(d[v]>d[u]+w) {
d[v]=d[u]+w;
if(!inq[v]) inq[v]=,q.push(v);
}
}
}
}
void dfs(int u) {
vis[u]=;
for(int i=;i<g[u].size();i++) {
int v=g[u][i].v,w=g[u][i].w;
if(!vis[v] && d[v]==d[u]+w) {
G[u].push_back(Edge(v,w));
G[v].push_back(Edge(u,w));
dfs(v);
}
}
}
void getroot(int u) {
siz[u]=; mx[u]=;
for(int i=;i<G[u].size();i++) {
int v=G[u][i].v;
if(v!=fa[u] && !vis[v]) {
fa[v]=u;
getroot(v);
siz[u]+=siz[v];
if(siz[v]>mx[u]) mx[u]=siz[v];
}
}
mx[u]=max(mx[u],size-siz[u]);
if(mx[u]<mx[root]) root=u;
}
int f[N][],tmp[N][];
void solve(int u,int S){
vis[u]=; f[][]=;
int m=G[u].size();
for(int i=;i<m;i++) {
int v=G[u][i].v;
if(!vis[v]) {
while(!q.empty()) q.pop(); //clear
q.push(v),dep[v]=,dis[v]=G[u][i].w,fa[v]=u;
while(!q.empty()) {
int now=q.front(); q.pop();
int k=dep[now];
if(k>K) break;
if(dis[now]>tmp[k][])
tmp[k][]=dis[now],tmp[k][]=;
if(dis[now]==tmp[k][]) tmp[k][]++;
for(int j=;j<G[now].size();j++) {
int to=G[now][j].v;
if(!vis[to] && to!=fa[now]) {
fa[to]=now;
dep[to]=dep[now]+;
dis[to]=dis[now]+G[now][j].w;
q.push(to);
}
}
}
//for(int j=1;j<=K;j++) printf("(%d,%d) ",tmp[j][0],tmp[j][1]);cout<<endl;
for(int j=;j<=K;j++) { //tmp位于前可以取[1..K]
if(tmp[j][]+f[K-j][]>ans1)
ans1=tmp[j][]+f[K-j][],ans2=;
if(tmp[j][]+f[K-j][]==ans1)
ans2+=tmp[j][]*f[K-j][];
}
for(int j=;j<=K;j++) {
if(tmp[j][]>f[j][]) f[j][]=tmp[j][],f[j][]=;
if(tmp[j][]==f[j][]) f[j][]+=tmp[j][];
tmp[j][]=tmp[j][]=;
}
}
}
//cout<<u<<": "<<ans1<<" "<<ans2<<endl;
for(int j=;j<=K;j++) f[j][]=f[j][]=;
m=G[u].size();
for(int i=;i<m;i++) {
int v=G[u][i].v;
if(!vis[v]) {
size=siz[v];
if(siz[v]>siz[u]) siz[v]=S-siz[v];
root=;
if(size>=K) getroot(v);
solve(root,siz[v]);
}
}
}
void read(int& x) {
char c=getchar(); int f=; x=;
while(!isdigit(c)){if(c=='-') f=-;c=getchar();}
while(isdigit(c)) x=x*+c-'',c=getchar();
x*=f;
}
int main() {
//freopen("in.in","r",stdin);
//freopen("out.out","w",stdout);
read(n),read(m),read(K); K--;
int u,v,w;
for(int i=;i<m;i++) {
read(u),read(v),read(w);
g[u].push_back(Edge(v,w));
g[v].push_back(Edge(u,w));
}
for(int i=;i<=n;i++)
sort(g[i].begin(),g[i].end());
spfa();
memset(vis,,sizeof(vis));
dfs();
size=n; mx[]=INF; root=;
memset(vis,,sizeof(vis));
getroot() , solve(root,size);
printf("%d %d",ans1,ans2);
return ;
}

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

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

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

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

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

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

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

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

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

  5. “中兴捧月”比赛之——二叉查找树(BST)树的最短路径Java求解

    问题描述: BST树,又称二叉查找树,求其到所有叶子节点路径的最小值 测试用例一:  10 5 20 返回15: 测试用例二: 100 20 70 110 120 10 null null 89 nu ...

  6. 经典树与图论(最小生成树、哈夫曼树、最短路径问题---Dijkstra算法)

    参考网址: https://www.jianshu.com/p/cb5af6b5096d 算法导论--最小生成树 最小生成树:在连通网的所有生成树中,所有边的代价和最小的生成树,称为最小生成树. im ...

  7. [BZOJ 1576] [Usaco2009 Jan] 安全路经Travel 【树链剖分】

    题目链接: BZOJ - 1576 题目分析 首先Orz Hzwer的题解. 先使用 dijikstra 求出最短路径树. 那么对于一条不在最短路径树上的边 (u -> v, w) 我们可以先沿 ...

  8. bzoj 1576 [Usaco2009 Jan]安全路经Travel(树链剖分,线段树)

    [题意] 给定一个无向图,找到1-i所有的次短路经,要求与最短路径的最后一条边不重叠. [思路] 首先用dijkstra算法构造以1为根的最短路树. 将一条无向边看作两条有向边,考察一条不在最短路树上 ...

  9. 主席树||可持久化线段树+离散化 || 莫队+分块 ||BZOJ 3585: mex || Luogu P4137 Rmq Problem / mex

    题面:Rmq Problem / mex 题解: 先离散化,然后插一堆空白,大体就是如果(对于以a.data<b.data排序后的A)A[i-1].data+1!=A[i].data,则插一个空 ...

随机推荐

  1. (hdu)1022 Train Problem I 火车进站问题

    题目链接:http://acm.split.hdu.edu.cn/showproblem.php?pid=1022 Problem Description As the new term comes, ...

  2. ASP.NET缓存 Cache

    缓存介绍 如果每次进入页面的时候都查询数据库生成页面内容的话,如果访问量非常大,则网站性能会非常差,而如果只有第一次访问的时候才查询数据库生成页面内容,以后都直接输出内容,则能提高系统性能,这样无论多 ...

  3. You have new mail in /var/spool/mail/root 烦不烦你(转)

    转自(http://blog.csdn.net/yx_l128125/article/details/7425182) 有时在进入系统的时候经常提示You have new mail in /var/ ...

  4. tmux复制到windows剪贴板/粘贴板的坑

    以下所有操作都是在windows下面用putty连接linux centos6的情景下. 一直很纳闷为什么在tmux模式下不能把复制到的文字放到系统的粘贴板里面呢?通过层层阻碍,终于找到了原因. 去掉 ...

  5. PHP 面向对象之自定义类

    所谓面向对象就是什么时候什么东西做什么,我们设计类的时候需要想的就是怎么做的内容,那么怎么样的一个类才算是符合OOP的思想呢,答案是:这个类写好之后,在使用的过程中,能准确的代表一个事物,在书写的时候 ...

  6. CGDataCmd

    1,"Get Inf Joint from file" 选择文件中储存的骨骼信息; 2,"Export skinWeight"   导出权重;  3," ...

  7. 2014年度辛星html教程夏季版第二节

    上面一节中我们介绍了HTML文件的书写和几个标签,接下来我们来认识几个其他的标签,这里我们主要介绍一下head标签和文本标签. ***************head标签*************** ...

  8. 图片Base64编码 简单使用

    图片在线转换Base64,图片编码base64 http://tool.css-js.com/base64.html HTML5 + js <input type="file" ...

  9. LightOj_1287 Where to Run

    题目链接 题意: 有n个街口和m条街道, 你后边跟着警察,你需要进行大逃亡(又是大爱的抢银行啊),在每个街口你都有≥1个选择, 1)停留在原地5分钟. 2)如果这个街口可以到xi这个街口, 并且, 通 ...

  10. Performance Test of List<T>, LinkedList<T>, Queue<T>, ConcurrentQueue<T>

    //Test Group 1 { var watch = Stopwatch.StartNew(); var list = new List<int>(); ; j < ; j++) ...