zoukankan      html  css  js  c++  java
  • 圆方树小结

    圆方树

    jzoj 1914. 【2011集训队出题】最短路
    这是道圆方树+倍增LCA裸题。
    圆方树,顾名思义,就是圆点和方点所组成的树。
    而方点就是一个圆的根,一般都是(dfs)时第一个到这个圆的那个位置,然后另附一个点当做方点。然后圆所组成的点都连向方点。
    而对于这种圆方边的边权,则为它到根的最近值。
    从而将一个仙人掌转成了一棵树。

    然后对于这棵树,我们就可以用倍增来求出两两点之间的最短路了。
    注意的是,对于最后走到的位置,我们要看看它是从上面绕近还是直接从下面走更优!!!
    就这样子了。

    (code)

    #include <cstdio>
    #include <algorithm>
    #define N 100010
    #define mem(x, a) memset(x, a, sizeof x)
    #define fo(x, a, b) for (int x = (a); x <= (b); x++)
    #define fd(x, a, b) for (int x = (a); x >= (b); x--)
    using namespace std;
    struct node{int v, fr, w;}e[N << 1];
    struct edge{int v, fr;}g[N << 1];
    int n, n1, m, Q, tail[N], cnt = 1, len[N];
    int dfn[N], low[N], fa[N], tot = 0, ri[N];
    int f[N][16], l[N][16], cir[N], fz[N], dep[N];
    int head[N], cnt1 = 1;
    int z[N], top = 0;
    
    inline int read()
    {
    	int x = 0, f = 0; char c = getchar();
    	while (c < '0' || c > '9') f = (c == '-') ? 1 : f, c = getchar();
    	while (c >= '0' && c <= '9') x = (x << 1) + (x << 3) + (c ^ 48), c = getchar();
    	return f ? -x : x;
    }
    
    inline void add(int u, int v, int w) {e[++cnt] = (node){v, tail[u], w}; tail[u] = cnt;}
    
    inline void add1(int u, int v) {g[++cnt1] = (edge){v, head[u]}; head[u] = cnt1;}
    
    void tarjan(int x)
    {
    	dfn[x] = low[x] = ++tot, z[++top] = x;
    	for (int p = tail[x], v; p; p = e[p].fr)
    	{
    		v = e[p].v;
    		if (! dfn[v])
    		{
    			fa[v] = x, len[v] = e[p].w;
    			tarjan(v);
    			low[x] = min(low[x], low[v]);
    			if (low[v] >= dfn[x])
    			{
    				cir[++n] = fz[z[top]], add1(x, n);
    				int u = top;
    				while (z[u] != x)	
    					cir[n] += len[z[u]], add1(n, z[u]), u--;
    				ri[z[u]] = 0, u++;
    				while (u <= top) ri[z[u]] = ri[z[u - 1]] + len[z[u]], u++;
    				while (z[top] != x) l[z[top]][0] = min(ri[z[top]], cir[n] - ri[z[top]]), top--;
    			}
    		}
    		else if (dfn[v] < low[x])
    			fz[x] = e[p].w, low[x] = dfn[v];
    	}
    }
    
    void get_dep(int x)
    {
    	for (int p = head[x], v; p; p = g[p].fr)
    		v = g[p].v, f[v][0] = x, dep[v] = dep[x] + 1, get_dep(v);
    }
    
    int LCA(int x, int y)
    {
    	int ans = 0;
    	if (dep[x] < dep[y]) swap(x, y);
    	for (int i = 0, cha = dep[x] - dep[y]; cha; i++, cha >>= 1)
    		if (cha & 1) ans += l[x][i], x = f[x][i];
    	if (x == y) return ans;
    	fd(i, 14, 0)
    		if (f[x][i] != f[y][i])
    		{
    			ans += l[x][i] + l[y][i];
    			x = f[x][i], y = f[y][i];
    		}
    	if (cir[f[x][0]]) return ans + min(abs(ri[x] - ri[y]), cir[f[x][0]] - abs(ri[x] - ri[y]));
    	else return ans + l[x][0] + l[y][0];
    }
    
    int main()
    {
    	n = n1 = read(), m = read(), Q = read();
    	fo(i, 1, m)
    	{
    		int u = read(), v = read(), w = read();
    		add(u, v, w), add(v, u, w);
    	}
    	tarjan(1), get_dep(1);
    	fo(j, 1, 14)
    		fo(i, 1, n)
    		{
    			f[i][j] = f[f[i][j - 1]][j - 1];
    			l[i][j] = l[i][j - 1] + l[f[i][j - 1]][j - 1];
    		}
    	fo(i, 1, Q)
    	{
    		int u = read(), v = read();
    		printf("%d
    ", LCA(u, v));
    	}
    	return 0;
    }
    
    转载需注明出处。
  • 相关阅读:
    关于AJAX与form表单提交数据的格式
    MongoDB
    Redis
    在django中使用django_debug_toolbar进行日志记录
    python第三方库,你要的这里都有
    Django之用户认证auth模块
    Django中常用命令
    form表单钩子,局部钩子和全局钩子
    当我开始爱自己
    FOR YOU
  • 原文地址:https://www.cnblogs.com/jz929/p/12168579.html
Copyright © 2011-2022 走看看