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

----------------------------------------------------------------------------

#include<queue>
#include<cctype>
#include<cstdio>
#include<cstring>
#include<algorithm>
 
using namespace std;
 
const int maxn = 30009;
const int INF = 0X3F3F3F3F;
 
inline int getint() {
char c = getchar();
for(; !isdigit(c); c = getchar());
int ret = 0;
for(; isdigit(c); c = getchar())
ret = ret * 10 + c - '0';
return ret;
}
 
int N, K, n = 0;
int d[maxn], seq[maxn << 1], w[maxn << 1], r[maxn << 1], L[maxn], R[maxn];
bool vis[maxn];
 
inline void Max(int &x, int t) {
if(t > x) x = t;
}
 
struct edge {
int t, w;
bool f;
edge* n;
} E[maxn << 2], *pt = E, *H[maxn];
 
inline void AddEdge(int u, int v, int w) {
pt->f = 0, pt->t = v, pt->w = w, pt->n = H[u], H[u] = pt++;
}
 
struct node {
int n, w;
node(int _n, int _w) : n(_n), w(_w) {
}
bool operator < (const node &o) const {
return w > o.w;
}
};
 
priority_queue<node> q;
 
void Dijkstra() {
for(int i = 0; i < N; i++) d[i] = INF;
d[0] = 0;
q.push(node(0, 0));
while(!q.empty()) {
node o = q.top(); q.pop();
if(d[o.n] != o.w) continue;
for(edge* e = H[o.n]; e; e = e->n) if(d[e->t] > d[o.n] + e->w) {
d[e->t] = d[o.n] + e->w;
q.push(node(e->t, d[e->t]));
}
}
}
 
void Init() {
N = getint();
int m = getint();
K = getint();
while(m--) {
int u = getint() - 1, v = getint() - 1, w = getint();
AddEdge(u, v, w), AddEdge(v, u, w);
}
}
 
namespace F {
edge E[maxn << 1], *pt = E, *H[maxn];
bool vis[maxn];
int L[maxn], cnt[maxn], sz[maxn];
int Root, mn, n, ans, tot;
inline void AddEdge(int u, int v, int w) {
pt->t = v, pt->w = w, pt->n = H[u], H[u] = pt++;
}
void DFS(int x, int fa = -1) {
int mx = 0;
sz[x] = 1;
for(edge* e = H[x]; e; e = e->n) if(e->t != fa && !vis[e->t]) {
DFS(e->t, x);
sz[x] += sz[e->t];
Max(mx, sz[e->t]);
}
Max(mx, n - sz[x]);
if(mx < mn)
mn = mx, Root = x;
}
void dfs_upd(int x, int fa, int d, int c) {
if(c >= K) return;
if(cnt[K - c - 1] && d + L[K - c - 1] > ans)
ans = d + L[K - c - 1], tot = cnt[K - c - 1];
else if(d + L[K - c - 1] == ans)
tot += cnt[K - c - 1];
c++;
for(edge* e = H[x]; e; e = e->n)
if(e->t != fa && !vis[e->t]) dfs_upd(e->t, x, d + e->w, c);
}
void dfs_add(int x, int fa, int d, int c) {
if(c >= K) return;
if(d > L[c])
L[c] = d, cnt[c] = 1;
else if(d == L[c])
cnt[c]++;
c++;
for(edge* e = H[x]; e; e = e->n)
if(e->t != fa && !vis[e->t]) dfs_add(e->t, x, d + e->w, c);
}
void Solve(int x) {
mn = maxn, DFS(x);
for(int i = 0; i <= sz[x]; i++) L[i] = cnt[i] = 0;
x = Root;
cnt[0] = 1;
for(edge* e = H[x]; e; e = e->n) if(!vis[e->t]) {
dfs_upd(e->t, x, e->w, 1);
dfs_add(e->t, x, e->w, 1);
}
DFS(x);
vis[x] = true;
for(edge* e = H[x]; e; e = e->n)
if(!vis[e->t]) n = sz[e->t], Solve(e->t);
}
void Work() {
for(int i = 0; i < N; i++)
vis[i] = false;
ans = tot = 0;
n = N;
Solve(0);
printf("%d %d\n", ans, tot);
}
}
 
bool Cmp(const int &l, const int &r) {
return seq[l] < seq[r];
}
 
void dfs(int x) {
seq[L[x] = ++n] = x;
r[n] = n;
vis[x] = true;
for(edge* e = H[x]; e; e = e->n) if(!vis[e->t] && d[e->t] == d[x] + e->w) {
seq[++n] = e->t;
w[n] = e->w;
r[n] = n;
}
R[x] = n;
sort(r + L[x], r + R[x] + 1, Cmp);
for(int i = L[x]; i <= R[x]; i++) if(!vis[seq[r[i]]]) {
F::AddEdge(x, seq[r[i]], w[r[i]]);
F::AddEdge(seq[r[i]], x, w[r[i]]);
dfs(seq[r[i]]);
}
}
 
void Build() {
for(int i = 0; i < N; i++) vis[i] = false;
dfs(0);
}
 
int main() {
Init();
Dijkstra();
Build();
F::Work();
return 0;
}

----------------------------------------------------------------------------

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]最短路径树问题 (贪心+点分治)

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

  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. BZOJ_4016_[FJOI2014]最短路径树问题_最短路+点分治

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

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

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

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

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

  9. 洛谷 [FJOI2014]最短路径树问题 解题报告

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

随机推荐

  1. ActionScript简单实现Socket Tcp应用协议分析器

    转自..smark http://www.cnblogs.com/smark/archive/2012/05/15/2501507.html ActionScript简单实现Socket Tcp应用协 ...

  2. 基于HTML5多图片Ajax上传可预览

    html5多图控件<input id="fileImage" type="file" size="30" name="fil ...

  3. DB2数据库常用基本操作命令

    点击开始菜单-->所有程序-->IBM-->DB2-->DB2COPY1-->命令行工具-->命令窗口一.DB2实例操作1.查看DB2数据库的版本及安装目录 E:\ ...

  4. random background

    function roll(){ var bg = document.getElementById("loginbg"); var rnd = Math.floor(Math.ra ...

  5. Silverlight学习(五)图形标绘

    Silverlight中进行图形标绘的方法太多了,这里的标绘和Arcgis中的标绘不同,这里大多是静态的标绘.标绘的方法主要有Path(路径标记法).直接标绘(Line等).几何标记(LineGeom ...

  6. An Data-Scientist Prepares 《数据科学家的自我修养》

    从今天开始,博主将用大概1000天的时间记录自己学习并成为初级数据科学家(数据分析师)的心路历程. 包括数据科学家所必需的的基础知识:数学,统计,计算机,商业,沟通能力等. 希望博主能够在2017前完 ...

  7. android欢迎页源码

    直接上源码: import android.app.Activity; import android.content.Intent; import android.os.Bundle; import ...

  8. 私有构造函数(c# .NET)

    如果类成员有private修饰符,就不允许在类范围以外访问这个类成员.对类构造函数应用private修饰符时,则禁止外部类创建该类的实例.尽管看上去有些不好理解(既然不能实例化,那么这个类还有什么用处 ...

  9. (转)对mysql explain讲的比较清楚的

    转自:http://www.blogjava.net/persister/archive/2008/10/27/236813.html 在 explain的帮助下,您就知道什么时候该给表添加索引,以使 ...

  10. 关于Git和Github

    英文原文:Ten Things You Didn't Know Git And GitHub Could Do Git 和 GitHub 都是非常强大的工具.即使你已经使用他们很长时间,你也很有可能不 ...