hdu 2874Connections between cities LCA

题目链接

给n个城市, m条边, q个询问, 每个询问, 输出城市a和b的最短距离, 如果不联通, 输出not connected。

用并查集判联通, 如果不连通, 那么两个联通块之间加一条权值很大的边。 然后树链剖分.....

#include <iostream>
#include <vector>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <map>
#include <set>
#include <string>
#include <queue>
#include <stack>
#include <bitset>
using namespace std;
#define pb(x) push_back(x)
#define ll long long
#define mk(x, y) make_pair(x, y)
#define lson l, m, rt<<1
#define mem(a) memset(a, 0, sizeof(a))
#define rson m+1, r, rt<<1|1
#define mem1(a) memset(a, -1, sizeof(a))
#define mem2(a) memset(a, 0x3f, sizeof(a))
#define rep(i, n, a) for(int i = a; i<n; i++)
#define fi first
#define se second
typedef pair<int, int> pll;
const double PI = acos(-1.0);
const double eps = 1e-8;
const int mod = 1e9+7;
const int inf = 1061109567;
const int dir[][2] = { {-1, 0}, {1, 0}, {0, -1}, {0, 1} };
const int maxn = 10005;
int head[maxn*2], fa[maxn], son[maxn], sz[maxn], deep[maxn], top[maxn], w[maxn], f[maxn], cnt, num;
ll sum[maxn<<2];
struct node
{
    int to, nextt, w;
}e[maxn*2];
struct ed
{
    int u, v;
    ll w;
    ed(){}
    ed(int u, int v, ll w):u(u),v(v),w(w){}
}edge[maxn];
void init() {
    mem1(head);
    num = cnt = 0;
}
void add(int u, int v, int w) {
    e[num].to = v, e[num].nextt = head[u], e[num].w = w, head[u] = num++;
}
void dfs1(int u, int fa) {
    sz[u] = 1;
    deep[u] = deep[fa]+1;
    son[u] = -1;
    f[u] = fa;
    for(int i = head[u]; ~i; i = e[i].nextt) {
        int v = e[i].to;
        if(v == fa)
            continue;
        dfs1(v, u);
        sz[u] += sz[v];
        if(son[u]==-1||sz[v]>sz[son[u]])
            son[u] = v;
    }
}
void dfs2(int u, int tp) {
    w[u] = ++cnt, top[u] = tp;
    if(~son[u])
        dfs2(son[u], tp);
    for(int i = head[u]; ~i; i = e[i].nextt) {
        int v = e[i].to;
        if(v == f[u]||v == son[u])
            continue;
        dfs2(v, v);
    }
}
void pushUp(int rt) {
    sum[rt] = sum[rt<<1]+sum[rt<<1|1];
}
void update(int p, ll val, int l, int r, int rt) {
    if(l == r) {
        sum[rt] = val;
        return ;
    }
    int m = l+r>>1;
    if(p<=m)
        update(p, val, lson);
    else
        update(p, val, rson);
    pushUp(rt);
}
ll query(int L, int R, int l, int r, int rt) {
    if(L<=l&&R>=r) {
        return sum[rt];
    }
    int m = l+r>>1;
    ll ret = 0;
    if(L<=m)
        ret += query(L, R, lson);
    if(R>m)
        ret += query(L, R, rson);
    return ret;
}
ll find(int u, int v) {
    int f1 = top[u], f2 = top[v];
    ll ret = 0;
    while(f1 != f2) {
        if(deep[f1]<deep[f2]) {
            swap(f1, f2);
            swap(u, v);
        }
        ret += query(w[f1], w[u], 1, cnt, 1);
        u = f[f1];
        f1 = top[u];
    }
    if(u == v)
        return ret;
    if(deep[u]>deep[v])
        swap(u, v);
    ret += query(w[son[u]], w[v], 1, cnt, 1);
    return ret;
}
int findd(int u) {
    return fa[u] == u?u:findd(fa[u]);
}
int main()
{
    int n, m, q, x, y, z;
    while(cin>>n>>m>>q) {
        init();
        int ecnt = 0;
        for(int i = 1; i<=n; i++)
            fa[i] = i;
        for(int i = 0; i<m; i++) {
            scanf("%d%d%d", &x, &y, &z);
            add(x, y, z);
            add(y, x, z);
            edge[ecnt++] = ed(x, y, z);
            x = findd(x);
            y = findd(y);
            if(x!=y)
                fa[x] = y;
        }
        x = findd(1);
        for(int i = 2; i<=n; i++) {
            y = findd(i);
            if(y!=x) {
                fa[y] = x;
                edge[ecnt++] = ed(x, y, (ll)1e12);
                add(x, y, inf);
                add(y, x, inf);
            }
        }
        dfs1(1, 0);
        dfs2(1, 1);
        for(int i = 0; i<ecnt; i++) {
            if(deep[edge[i].u]>deep[edge[i].v]) {
                swap(edge[i].u, edge[i].v);
            }
            update(w[edge[i].v], edge[i].w, 1, cnt, 1);
        }
        while(q--) {
            scanf("%d%d", &x, &y);
            ll ans = find(x, y);
            if(ans>=1e12) {
                puts("Not connected");
            } else {
                printf("%d\n", ans);
            }
        }
    }

    return 0;
}
时间: 2024-10-31 12:05:16

hdu 2874Connections between cities LCA的相关文章

HDU 4822 Tri-war(LCA树上倍增)(2013 Asia Regional Changchun)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4822 Problem Description Three countries, Red, Yellow, and Blue are in war. The map of battlefield is a tree, which means that there are N nodes and (N – 1) edges that connect all the nodes. Each country

HDU - 2874 Connections between cities(LCA)

题目大意:给出N个点,M条线,Q个询问,询问的是两点之间的最短距离 解题思路:恶心的数据量,一不小心就超空间了 这题给图不是张连通图,是森林,所以计算两点之间的最短距离时还要考虑一下是否在同一棵树中 剩下的就是裸LCA了 #include <cstdio> #include <cstring> #define N 10010 #define M 20010 #define C 2000010 struct Edge{ int to, next, dis; }E[M]; struct

HDU 2874 Connections between cities(LCA离线)

 题意:一个森林,询问两个节点距离,若无法到达,输出Not connected. 思路:还是求LCA的思想,只需再对每个询问的两个节点判断是否在一棵树内即可. 有一个问题是这道题的query很大,达到了1000000,所以离线算法空间上比较虚, 然而只会离线的.....于是把int改成short int险过.... #include<cstdio> #include<cstring> #include<cmath> #include<cstdlib> #

hdu-2874 Connections between cities(lca+tarjan+并查集)

题目链接: Connections between cities Time Limit: 10000/5000 MS (Java/Others)     Memory Limit: 32768/32768 K (Java/Others) Problem Description After World War X, a lot of cities have been seriously damaged, and we need to rebuild those cities. However, s

hdu 6031 Innumerable Ancestors(LCA+剪枝)

题目链接:hdu 6031 Innumerable Ancestors 题意: 给你一棵n个节点的树,现在有m个询问,每次给你两个点集a,b. 让你从a,b点集中选两个点x,y,使得这两个点的LCA的深度最大. 题解: 标解应该是二分+LCA,不过我试了一下暴力,稍微剪了点枝,就直接过去了. 具体看代码 1 #include<bits/stdc++.h> 2 #define F(i,a,b) for(int i=a;i<=b;i++) 3 using namespace std; 4 c

HDU 3966 dfs序+LCA+树状数组

题目意思很明白: 给你一棵有n个节点的树,对树有下列操作: I c1 c2 k 意思是把从c1节点到c2节点路径上的点权值加上k D c1 c2 k 意思是把从c1节点到c2节点路径上的点权值减去k Q a 查询节点a的权值 数据大小 节点个数 n[1,50000], 操作次数 op[0,30000]; 不会树链剖分 故只有想其他的方法. 这道题有点类似今年上海网络赛的1003 ,不过那题我没做: 算法思路: 以节点1 为根,求出节点i 的 dfs序列 tim[i][2]; 其中tim[i][0

Connections between cities LCA

Problem Description After World War X, a lot of cities have been seriously damaged, and we need to rebuild those cities. However, some materials needed can only be produced in certain places. So we need to transport these materials from city to city.

HDU - 6115 Factory (LCA 倍增)

题目传送门:HDU - 6115  Factory 题目大意: (中文题,简单解答下题意) 存在N个城市和M个百度的子公司,N个城市间有N-1条道路连接(一颗树),每个子公司都有办公室,办公室分布在各个城市,现在提问,两个子公司间的最小距离. 分析: 枚举提问的两个子公司的办公室间的距离,求出最短距离即可: 例如:子公司company1办公室在城市 1 2 3     子公司company2的办公室在城市5 6 ,若求company1,company2的最短距离,即枚举(1,5).(1,6).(

HDU - 4547 CD操作 (LCA倍增)

题目传送门:HDU - 4547 CD操作 题目大意: 略 分析: 求出目录A 到 B所需要的CD操作次数,这里的A B 位字符串 所以用到map映射,之后直接求LCA分情况讨论即可:设求A到B的CD操作数 1.A==B  需要的CD操作数是0 2.A是B的最近公共祖先,则A-->B的CD操作数是0 3.B是A的最近公共祖先,则B-->A的CD操作数是 deep[B]-deep[B] 4.若互相不是最近公共祖先,则CD操作数是 deep[A]-deep[lca(A,B)]+1 #include