HDU 4750 Count The Pairs ★(图+并查集+树状数组)
题意
给定一个无向图(N<=10000, E<=500000),定义f[s,t]表示从s到t经过的每条路径中最长的边的最小值。Q个询问,每个询问一个t,问有多少对(s, t)使得f[s, t] >= t((s,t)和(t,s)是两对)
思路
按边权从小到大排序。考虑从小到大往图中加边同时计算以加入的边为f值的点对数。
难点和重点在于用并查集维护边的连通情况。
对于新加入的边(u, v),如果u,v原来便连通,则没有以该边为f值的点对,因为它一定不是最小边。
而如果(u, v)不连通,就可以把这条边能到达的点分为和u连通以及和v连通(分别和u、v在同一并查集中),那么分别从u、 v的连通集中取一个点组成的点对的f值都是这条边,即答案 = 2 * |Union(u)| * |Union(v)|。所以并查集还需要维护各自集中的点个数。
最后用树状数组维护一下前缀和,询问的时候二分+查询前缀和即可。
代码
[cpp]
#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <string>
#include <cstring>
#include <vector>
#include <set>
#include <stack>
#include <queue>
#define MID(x,y) ((x+y)/2)
#define MEM(a,b) memset(a,b,sizeof(a))
#define REP(i, begin, end) for (int i = begin; i <= end; i ++)
using namespace std;
const int MAX = 500005;
struct BIT{
int t[MAX<<1];
int bound;
inline void init(int n){
bound = n;
MEM(t, 0);
}
//lowbit(x):求2^q, q是x二进制最右边的1的位置.
inline int lowbit(int x){
return x & (-x);
}
inline void update(int x, int v){
for (int i = x; i <= bound; i += lowbit(i))
t[i] += v;
}
inline int sum(int x){
int res = 0;
for (int i = x; i >= 1; i -= lowbit(i))
res += t[i];
return res;
}
}bit;
const int MAXN = 10005;
struct Disjoint_Sets{
struct Sets{
int father, ranks, num;
}S[MAXN];
inline void Init(int n){
for (int i = 0; i <= n; i ++){
S[i].father = i;
S[i].ranks = 0;
S[i].num = 1;
}
}
inline int Father(int x){
if (S[x].father == x){
return x;
}
else{
S[x].father = Father(S[x].father); //Path compression
return S[x].father;
}
}
inline bool Union(int x, int y){
int fx = Father(x), fy = Father(y);
if (fx == fy){
return false;
}
else{ //Rank merge
int num1 = S[fx].num, num2 = S[fy].num;
if (S[fx].ranks > S[fy].ranks){
S[fy].father = fx;
}
else{
S[fx].father = fy;
if (S[fx].ranks == S[fy].ranks){
++ S[fy].ranks;
}
}
S[Father(fx)].num = num1+num2;
return true;
}
}
}DS;
struct que{
int t, res;
}q[100005];
struct edges{
int u, v, w;
}e[500005];
bool cmp(edges n1, edges n2){
return n1.w < n2.w;
}
vector <int> adj[10005];
int main(){
int n, m;
while(scanf("%d %d", &n, &m) != EOF){
for (int i = 0; i < m; i ++) scanf("%d %d %d", &e[i].u, &e[i].v, &e[i].w);
sort(e, e+m, cmp);
int Q;
scanf("%d", &Q);
for (int i = 0; i < Q; i ++){
scanf("%d", &q[i].t);
q[i].res = 0;
}
for (int i = 0; i <= n; i ++) adj[i].clear();
DS.Init(n);
bit.init(m);
for (int i = 0; i < m; i ++){
if (DS.Father(e[i].u) != DS.Father(e[i].v)){
bit.update(m - i, 2*DS.S[DS.Father(e[i].u)].num*DS.S[DS.Father(e[i].v)].num);
DS.Union(e[i].u, e[i].v);
}
}
for (int i = 0; i < Q; i ++){
int t = q[i].t;
int l = 0, r = m - 1;
while(l < r){
int mid = MID(l, r);
if (e[mid].w < t){
l = mid + 1;
}
else{
r = mid;
}
}
while (l < m && e[l].w < t) l ++;
printf("%d\n", bit.sum(m - l));
}
}
return 0;
}
[/cpp]
HDU 4750 Count The Pairs ★(图+并查集+树状数组)的更多相关文章
- HDU 4750 Count The Pairs (离线并查集)
按边从小到大排序. 对于每条边(from, to, dist),如果from和to在同一个集合中,那么这条边无意义,因为之前肯定有比它更小的边连接了from和to. 如果from和to不属于同一个集合 ...
- hdu 6200 mustedge mustedge(并查集+树状数组 或者 LCT 缩点)
hdu 6200 mustedge mustedge(并查集+树状数组 或者 LCT 缩点) 题意: 给一张无向连通图,有两种操作 1 u v 加一条边(u,v) 2 u v 计算u到v路径上桥的个数 ...
- BZOJ-3211花神游历各国 并查集+树状数组
一开始想写线段树区间开方,简单暴力下,但觉得变成复杂度稍高,懒惰了,编了个复杂度简单的 3211: 花神游历各国 Time Limit: 5 Sec Memory Limit: 128 MB Subm ...
- BZOJ3211 花神游历各国 并查集 树状数组
欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题目传送门 - BZOJ3211 题意概括 有n个数形成一个序列. m次操作. 有两种,分别是: 1. 区间开根(取整) 2. ...
- 【bzoj4869】[Shoi2017]相逢是问候 扩展欧拉定理+并查集+树状数组
题目描述 Informatik verbindet dich und mich. 信息将你我连结. B君希望以维护一个长度为n的数组,这个数组的下标为从1到n的正整数.一共有m个操作,可以分为两种:0 ...
- Hdu 5458 Stability (LCA + 并查集 + 树状数组 + 缩点)
题目链接: Hdu 5458 Stability 题目描述: 给出一个还有环和重边的图G,对图G有两种操作: 1 u v, 删除u与v之间的一天边 (保证这个边一定存在) 2 u v, 查询u到v的路 ...
- HDU 5458 Stability(双连通分量+LCA+并查集+树状数组)(2015 ACM/ICPC Asia Regional Shenyang Online)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5458 Problem Description Given an undirected connecte ...
- la4730(并查集+树状数组)
https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&category=30& ...
- 【BZOJ3211】花神游历各国 并查集+树状数组
[BZOJ3211]花神游历各国 Description Input Output 每次x=1时,每行一个整数,表示这次旅行的开心度 Sample Input 41 100 5 551 1 22 1 ...
随机推荐
- ios极光推送快速集成教程
内容中包含 base64string 图片造成字符过多,拒绝显示
- beego——session模块
session介绍 session是一个独立的模块,即你可以那这个模块应用于其它Go程序中. session模块是用来存储客户端用户,session目前只支持cookie方式的请求,如果客户端不支持c ...
- phpcms发布到服务器修改
请进行以下步骤的修改: 1.修改/caches/configs/system.php里面所有和域名有关的,把以前的老域名修改为新域名就可以了. 2.进行后台设置->站点管理 对相应的站点的域名进 ...
- spring boot 引导
链接:https://www.zhihu.com/question/39483566/answer/243413600 Spring Boot 的优点快速开发,特别适合构建微服务系统,另外给我们封装了 ...
- 开源BBS论坛软件推荐
七款开源BBS论坛软件推荐(1) 本文介绍了七个开源的BBS论坛软件(在英文界一般叫做Forum).可能国内的朋友们比较熟悉Discuz!和PHPwind,但其实我们的选择还是很多的,而且下面介绍的这 ...
- Zookeeper环境安装
源码包下载: http://archive.apache.org/dist/zookeeper/zookeeper-3.4.10 集群环境: master 192.168.1.99 slave1 19 ...
- 【python】win10中python3.5.2输入pip出现Fatal error in launcher: Unable to create process using '"'
系统:windows 10 python版本:3.5.2 出现的错误如下: C:\Users\zhuxy>pip list Fatal error in launcher: Unable to ...
- selenium 之定位方法
1 id 定位 driver.find_element_by_id() HTML 规定id 属性在HTML 文档中必须是唯一的.这类似于公民的身份证号,具有很强的唯一性 from selenium i ...
- javascript中常用函数汇总
js中函数很多,在实际项目开发中,函数的应用可以很大程度上简化我们的代码,所以在此记下开发中js中常用的函数,增强记忆. 1.isNaN(X):函数用于检查其参数是否是非数字值. 如果 x 是特殊的非 ...
- 验证url格式
//验证url var url=$("#address").val(); var regUrl = /^http[s]{0,1}:\/\/.+$/ ; if(url.match(r ...