题目链接【https://vjudge.net/problem/HDU-2874】

题意: 输入一个森林,总节点不超过N(N<10000),由C次询问(C<1000000),每次询问两个点,如果来联通输出,两点之间的距离,如果不来联通,输出“Not connected”;

思路:首先判断u,v两个点在不在同一个树上,用并查集来做,如果在,就求两者的LCA,输入距离dis[u->v]=dis[u]+dis[v]-2*dis[LCA(u,v)]。

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn = ;
int N, M, C;
struct node
{
int id, next, len;
} E[maxn << ];
int head[maxn << ], num;
void initlist()
{
memset(head, -, sizeof(head));
num = ;
}
void adde(int u, int v, int len)
{
E[num].id = u;
E[num].len = len;
E[num].next = head[v];
head[v] = num++;
}
//----------------------------------------邻接表
int fa[maxn<<];
void initfa()
{
for(int i = ; i <= N; i++)
fa[i] = i;
}
int Find(int id)
{
if(id == fa[id]) return id;
else return fa[id] = Find(fa[id]);
}
void addu(int u, int v)
{
int x = Find(u);
int y = Find(v);
if(x != y) fa[x] = y;
}
//----------------------------------------并查集
int p[][maxn], dep[maxn], dis[maxn], vis[maxn];
void DFS(int u, int FA)
{
vis[u] = ;
for(int l = head[u]; l != -; l = E[l].next)
{
int id = E[l].id;
if(id == FA||vis[id]) continue;
dep[id] = dep[u] + ;
dis[id] = dis[u] + E[l].len;
p[][id] = u;
DFS(id, u);
}
}
void initlca()
{
memset(p, -, sizeof(p));
memset(dep,,sizeof(dep));
memset(dis, , sizeof(dis));
memset(vis, , sizeof(vis));
for(int i = ; i <= N; i++)
{
if(!vis[i])
DFS(i, -);
}
for(int k = ; k + <= ; k++)
for(int u = ; u <= N; u++)
{
if(p[k][u] < ) p[k + ][u] = -;
else
p[k + ][u] = p[k][p[k][u]];
}
}
int LCA(int u, int v)
{
if(dep[u] > dep[v]) swap(u, v);
for(int k = ; k <= ; k++)
{
if((dep[v] - dep[u]) >> k & )
v = p[k][v];
}
if(u == v) return u;
for(int k = ; k >= ; k--)
{
if(p[k][u] != p[k][v])
{
u = p[k][u];
v = p[k][v];
}
}
return p[][u];
}
//----------------------------------------LCA
int main ()
{
while(~scanf("%d%d%d", &N, &M, &C))
{
initlist();
initfa();
int u, v, ds;
for(int i = ; i <= M; i++)
{
scanf("%d%d%d", &u, &v, &ds);
adde(u, v, ds);
adde(v, u, ds);
addu(u, v);
}
initlca();
for(int i=;i<=C;i++)
{
scanf("%d%d",&u,&v);
int x=Find(u);
int y=Find(v);
if(x==y)
{
printf("%d\n",dis[u]+dis[v]-*dis[LCA(u,v)]);
}
else
printf("Not connected\n");
}
}
return ;
}
//#include<bits/stdc++.h>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int MAXN = ;
//---------------------------------//邻接表
struct node
{
int to, len, next;
} E[MAXN * ];
int p[MAXN * ], tot;
void init()
{
memset(p, -, sizeof(p));
tot = ;
}
void add(int u, int v, int len)
{
E[tot].to = v;
E[tot].len = len;
E[tot].next = p[u];
p[u] = tot++;
}
//---------------------------------//并查集
int fa[MAXN * ];
void init2(int n)
{
for(int i = ; i <= n; i++)
fa[i] = i;
}
int Find(int x)
{
if(x == fa[x])
return fa[x];
else
return fa[x] = Find(fa[x]);
}
void join (int i, int j)
{
int x = Find(i);
int y = Find(j);
if(x != y) fa[y] = x;
}
//----------------------------------//LAC
int ver[MAXN * ], vis[MAXN], fst[MAXN], R[MAXN * ];
int dis[MAXN], KT[MAXN * ], dp[MAXN * ][];
void init3()
{
memset(vis, , sizeof(vis));
tot = ;
}
void DFS(int u, int dep, int len)
{
vis[u] = ;
ver[++tot] = u;
R[tot] = dep;
fst[u] = tot;
dis[u] = len;
for(int k = p[u]; k != -; k = E[k].next)
{
int v = E[k].to;
if(vis[v]) continue;
DFS(v, dep + , len + E[k].len);
ver[++tot] = u;
R[tot] = dep;
}
}
void ST(int n)
{
KT[] = ;
for(int i = ; i <= n; i++)
KT[i] = KT[i / ] + ;
for(int i = ; i <= n; i++)
dp[i][] = i;
for(int j = ; j <= KT[n]; j++)
for(int i = ; i + ( << j) - <= n; i++)
{
int x = dp[i][j - ];
int y = dp[i + ( << (j - ))][j - ];
dp[i][j] = R[x] < R[y] ? x : y;
}
}
int RMQ(int l, int r)
{
int k = KT[r - l + ];
int x = dp[l][k];
int y = dp[r - ( << k) + ][k];
return R[x] < R[y] ? x : y;
}
int LCA(int u, int v)
{
int l = fst[u], r = fst[v];
if(l > r) swap(l, r);
int t = RMQ(l, r);
return ver[t];
}
//-------------------------------------//主函数
int N, M, C;
int main ()
{
while(~scanf("%d%d%d", &N, &M, &C))
{
init();//
init2(N);
int u, v, len;
for(int i = ; i <= M; i++)
{
scanf("%d%d%d", &u, &v, &len);
add(u, v, len);
add(v, u, len);
join(u, v);
}
init3();
for(int i = ; i <= N; i++)
{
if(vis[i]) continue;
DFS(i, , );
}
ST( * N - );
for(int i = ; i <= C; i++)
{
scanf("%d%d", &u, &v);
int x = Find(u);
int y = Find(v);
if(x != y)
{
printf("Not connected\n");
continue;
}
int lca = LCA(u, v);
printf("%d\n", dis[u] + dis[v] - * dis[lca]);
}
}
return ;
}

HDU2874【倍增、ST】的更多相关文章

  1. caioj 1237: 【最近公共祖先】树上任意两点的距离 在线倍增ST

    caioj 1237: [最近公共祖先]树上任意两点的距离 倍增ST 题目链接:http://caioj.cn/problem.php?id=1237 思路: 针对询问次数多的时候,采取倍增求取LCA ...

  2. 浅谈 倍增/ST表

    命题描述 给定一个长度为 \(n\) 的序列,\(m\) 次询问区间最大值 分析 上面的问题肯定可以暴力对吧. 但暴力肯定不是最优对吧,所以我们直接就不考虑了... 于是引入:倍增 首先,倍增是个什么 ...

  3. P7599-[APIO2021]雨林跳跃【二分,倍增,ST表】

    正题 题目链接:https://www.luogu.com.cn/problem/P7599 题目大意 \(n\)棵树,在某棵树上时可以选择向左右两边第一棵比它高的树跳,现在\(q\)次询问从\([A ...

  4. poj 3264 倍增 ST表

    #include<iostream> #include<cmath> using namespace std; ; int a[maxn]; ]; ]; int quick(i ...

  5. 【BZOJ1047】[HAOI2007]理想的正方形 (倍增ST表)

    [HAOI2007]理想的正方形 题目描述 有一个\(a*b\)的整数组成的矩阵,现请你从中找出一个\(n*n\)的正方形区域,使得该区域所有数中的最大值和最小值的差最小. 输入输出格式 输入格式: ...

  6. poj3264Balanced Lineup(倍增ST表)

    Balanced Lineup Time Limit: 5000MS   Memory Limit: 65536K Total Submissions: 52328   Accepted: 24551 ...

  7. 倍增ST应用 选择客栈(提高组)

    重磅例题!ST表应用!提高组Getting! 1125: B15-倍增-习题:选择客栈[ST表应用] 时间限制: 1 Sec  内存限制: 128 MB提交: 35  解决: 12[提交] [状态] ...

  8. Problem 1016 咒文卷轴 优先队列+前缀和+rmq

    题目链接: 题目 Problem 1016 咒文卷轴 Time Limit: 3000 mSec Memory Limit : 131072 KB 问题描述 小Y 是一个魔法师,有一天他获得了一卷神秘 ...

  9. bzoj2342

    shoi题目好坑爹 首先自己测发现这道题如果用后缀数组+rmq处理每个点回文串能延伸长度的话会TLE (当然我用的是倍增+ST的方法,如果用三分构建后缀数组+笛卡尔树处理rmq我就不知道了): 关于最 ...

  10. 【解题报告】Math

    = =本来昨天就该发的,只是断网……. MATH  [题目描述] 小 x正在做他的数学作业,可是作业实在太难了.题目是这样的: 1.给定一个含有N个数的数列 V. 2.你可以从数列中恰好移除 K个数, ...

随机推荐

  1. ② 设计模式的艺术-02.简单工厂(Simple Factory)模式

    工厂模式 实现了创建者和调用者的分离. 详细分类:简单工厂模式.工厂方法模式.抽象工厂模式 面向对象设计的基本原则 OCP(开闭原则,Open-Closed Principle):一个软件的实体应当对 ...

  2. Redhat 7 之 Mariadb(mysql)

    Redhat7 之后mysql 改为Mariadba,由于mysql 被卖给了IBM, 有闭源的风险. 所以就另外开了一个新的分支,继续开源.Maria 来源于mysql开发者的女儿的名字. 1. 安 ...

  3. Problem 2278 YYS (FZU + java大数)

    题目链接:http://acm.fzu.edu.cn/problem.php?pid=2278 题目: 题意: 有n种卡牌,每种卡牌被抽到的概率为1/n,求收齐所有卡牌的天数的期望. 思路: 易推得公 ...

  4. 2017 ACM暑期多校联合训练 - Team 4 1012 HDU 6078 Wavel Sequence (模拟)

    题目链接 Problem Description Have you ever seen the wave? It's a wonderful view of nature. Little Q is a ...

  5. JavaScript 核心

    我们首先来看一下对象[Object]的概念,这也是 ECMASript 中最基本的概念. 对象 Object ECMAScript 是一门高度抽象的面向对象(object-oriented)语言,用以 ...

  6. Mysql储存过程8:repeat循环

    语法: repeat SQL until 条件 end repeat; 就是相当于其他语言中的: do{ # }while(); mysql> create procedure p1p() -& ...

  7. cin循环输入控制问题

    之前写一个简单的输入节点值自动生成链表的测试程序,发现cin的输入控制好像在VC++6.0和VS2010中不一样,特此记录. 现在有以下代码: vector<int> ivec; int ...

  8. Linux中fork()函数的底层实现【转】

    转自:http://blog.csdn.net/duoru_xiong/article/details/76358812 1. fork(),vfork(),clone()的区别 这三个系统调用的底层 ...

  9. python之smtplib库学习

    # -*- coding:utf-8 -*- import smtplibfrom email.mime.text import MIMETextfrom email import encodersf ...

  10. java实现ftp文件上传下载,解决慢,中文乱码,多个文件下载等问题

    //文件上传 public static boolean uploadToFTP(String url,int port,String username,String password,String ...