zoukankan      html  css  js  c++  java
  • bzoj3694 最短路

    Description

    给出一个 (n) 个点 (m) 条边的无向图, (n) 个点的编号从 (1) ~ (n) ,定义源点为 (1) 。定义最短路树如下:从源点 (1) 经过边集 (T) 到任意一点 (i) 有且仅有一条路径,且这条路径是整个图 (1)(i) 的最短路径,边集 (T) 构成最短路树。 给出最短路树,求对于除了源点 (1) 外的每个点 (i) ,求最短路,要求不经过给出的最短路树上的 (1)(i) 的路径的最后一条边。

    Input

    第一行包含两个数 (n)(m) ,表示图中有 (n) 个点和 (m) 条边。

    接下来 (m) 行,每行有四个数 (a_i,b_i,l_i,t_i) ,表示图中第 (i) 条边连接 (a_i)(b_i) 权值为 (l_i)(t_i)(1) 表示这条边是最短路树上的边, (t_i)(0) 表示不是最短路树上的边。

    Output

    输出 (n-1) 个数,第i个数表示从 (1)(i+1) 的要求的最短路。无法到达输出 (-1)

    Sample

    Sample Input

    5 9
    3 1 3 1
    1 4 2 1
    2 1 6 0
    2 3 4 0
    5 2 3 0
    3 2 2 1
    5 3 1 1
    3 5 2 0
    4 5 4 0
    

    Sample Output

    6 7 8 5
    

    Solution

    对于一条不在最短路树上的边,设它的端点为 (u)(v) ,长度为 (w) 。设 (t=lca(u,v))

    (t o u) 上的一个点 (x) 可以通过 (1 o t o v o u o x) 来到达,这样就不会经过最短路树上的边。

    此时 (ans[x] = dis[v] + w + dis[u] - dis[x]) 。所以我们需要最小化 (dis[v] + w + dis[u]) 。可以用树链剖分来搞。

    最开始把 (lca) 写假了还 (mathrm{wa}) 了三次(mathrm{TAT})

    #include<bits/stdc++.h>
    using namespace std;
    #define N 100001
    #define rep(i, a, b) for (int i = a; i <= b; i++)
    #define INF 0x7fffffff
    inline int read() {
    	int x = 0; char ch = getchar(); while (!isdigit(ch))  ch = getchar();
    	while (isdigit(ch)) x = (x << 1) + (x << 3) + ch - '0', ch = getchar(); return x;
    }
    int n, m, head[N], tot, cnt, fa[N], dep[N], siz[N], son[N], dis[N], ind, into[N], outo[N], bl[N], val[N << 2], tag[N << 2];
    struct edge { int v, w, next; }e[N << 1];
    struct edge2 { int u, v, w; }eg[N];
    inline void add(int u, int v, int w) { e[++tot].v = v, e[tot].w = w, e[tot].next = head[u], head[u] = tot; }
    void dfs(int u) {
    	siz[u] = 1;
    	for (int i = head[u], v; i; i = e[i].next) if ((v = e[i].v) != fa[u]) {
    		dep[v] = dep[u] + 1, fa[v] = u, dis[v] = dis[u] + e[i].w, dfs(v), siz[u] += siz[v];
    		if (siz[v] > siz[son[u]]) son[u] = v;
    	}
    }
    void dfs(int u, int top) {
    	bl[u] = top, into[u] = ++ind;
    	if (son[u]) dfs(son[u], top);
    	for (int i = head[u], v; i; i = e[i].next) if ((v = e[i].v) != fa[u] && v != son[u]) dfs(v, v);
    	outo[u] = ind;
    }
    inline int lca(int x, int y) {
    	for (; bl[x] != bl[y]; dep[bl[x]]>dep[bl[y]] ? x = fa[bl[x]] : y = fa[bl[y]]);
    	return dep[x]<dep[y] ? x : y;
    }
    #define ls rt << 1
    #define rs ls | 1
    #define mid (l + r >> 1)
    #define Min(a, b) a = min(a, b)
    void build(int rt, int l, int r) {
    	tag[rt] = INF;
    	if (l == r) { val[rt] = INF; return; }
    	build(ls, l, mid), build(rs, mid + 1, r);
    }
    void pushDown(int rt, int l, int r) {
    	if (tag[rt] == INF || l == r) return;
    	Min(tag[ls], tag[rt]), Min(tag[rs], tag[rt]);
    	if (mid == l) Min(val[ls], tag[rt]);
    	if (mid + 1 == r) Min(val[rs], tag[rt]);
    	tag[rt] = INF;
    }
    void update(int rt, int l, int r, int L, int R, int v) {
    	pushDown(rt, l, r);
    	if (l >= L && r <= R) {
    		Min(tag[rt], v);
    		if (l == r) Min(val[rt], v);
    		return;
    	}
    	if (L <= mid) update(ls, l, mid, L, R, v);
    	if (R > mid) update(rs, mid + 1, r, L, R, v);
    }
    void update(int u, int v, int w) {
    	while (bl[u] ^ bl[v]) update(1, 1, n, into[bl[u]], into[u], w), u = fa[bl[u]];
    	if (u ^ v) update(1, 1, n, into[v] + 1, into[u], w);
    }
    int ask(int rt, int l, int r, int p) {
    	pushDown(rt, l, r);
    	if (l == r) return val[rt];
    	if (p <= mid) return ask(ls, l, mid, p);
    	else return ask(rs, mid + 1, r, p);
    }
    int main() {
    	n = read(), m = read();
    	while (m--) {
    		int u = read(), v = read(), w = read(), t = read();
    		if (t) add(u, v, w), add(v, u, w);
    		else eg[++cnt].u = u, eg[cnt].v = v, eg[cnt].w = w;
    	}
    	dfs(1), dfs(1, 1), build(1, 1, n);
    	for (int i = 1; i <= cnt; i++) {
    		int t = lca(eg[i].u, eg[i].v), x = dis[eg[i].u] + dis[eg[i].v] + eg[i].w;
    		update(eg[i].u, t, x), update(eg[i].v, t, x);
    	}
    	for (int i = 2; i <= n; i++) {
    		int t = ask(1, 1, n, into[i]);
    		if (t ^ INF) printf("%d ", t - dis[i]);
    		else printf("-1 ");
    	}
    	return 0;
    }
    
  • 相关阅读:
    jquery编写插件的方法
    $.extend()的深拷贝和浅拷贝详细讲解
    jquery实现表格的搜索功能
    网页中tab标签切换分别用jquery和javascript源码实现
    JavaScript和jQuery的类型判断
    chrome jssip
    APiCloud学习
    vue生命周期、钩子函数
    闭包、作用域、原型小知识点等面试小知识点
    前后端分离
  • 原文地址:https://www.cnblogs.com/aziint/p/8658267.html
Copyright © 2011-2022 走看看