题意

给定一个无向图(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 ★(图+并查集+树状数组)的更多相关文章

  1. HDU 4750 Count The Pairs (离线并查集)

    按边从小到大排序. 对于每条边(from, to, dist),如果from和to在同一个集合中,那么这条边无意义,因为之前肯定有比它更小的边连接了from和to. 如果from和to不属于同一个集合 ...

  2. hdu 6200 mustedge mustedge(并查集+树状数组 或者 LCT 缩点)

    hdu 6200 mustedge mustedge(并查集+树状数组 或者 LCT 缩点) 题意: 给一张无向连通图,有两种操作 1 u v 加一条边(u,v) 2 u v 计算u到v路径上桥的个数 ...

  3. BZOJ-3211花神游历各国 并查集+树状数组

    一开始想写线段树区间开方,简单暴力下,但觉得变成复杂度稍高,懒惰了,编了个复杂度简单的 3211: 花神游历各国 Time Limit: 5 Sec Memory Limit: 128 MB Subm ...

  4. BZOJ3211 花神游历各国 并查集 树状数组

    欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题目传送门 - BZOJ3211 题意概括 有n个数形成一个序列. m次操作. 有两种,分别是: 1. 区间开根(取整) 2. ...

  5. 【bzoj4869】[Shoi2017]相逢是问候 扩展欧拉定理+并查集+树状数组

    题目描述 Informatik verbindet dich und mich. 信息将你我连结. B君希望以维护一个长度为n的数组,这个数组的下标为从1到n的正整数.一共有m个操作,可以分为两种:0 ...

  6. Hdu 5458 Stability (LCA + 并查集 + 树状数组 + 缩点)

    题目链接: Hdu 5458 Stability 题目描述: 给出一个还有环和重边的图G,对图G有两种操作: 1 u v, 删除u与v之间的一天边 (保证这个边一定存在) 2 u v, 查询u到v的路 ...

  7. 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 ...

  8. la4730(并查集+树状数组)

    https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&category=30& ...

  9. 【BZOJ3211】花神游历各国 并查集+树状数组

    [BZOJ3211]花神游历各国 Description Input Output 每次x=1时,每行一个整数,表示这次旅行的开心度 Sample Input 41 100 5 551 1 22 1 ...

随机推荐

  1. 自定义admin管理工具(stark组件)

    自定义admin管理工具(stark组件) 创建项目 了解了admin的功能后,我们可以开始仿照admin编写我们自己的管理工具stark组件 首先创建一个新的项目,并创建三个app stark就是我 ...

  2. SqoopFlume、Flume、HDFS之间比较

    Sqoop Flume HDFS Sqoop用于从结构化数据源,例如,RDBMS导入数据 Flume 用于移动批量流数据到HDFS HDFS使用 Hadoop 生态系统存储数据的分布式文件系统 Sqo ...

  3. GRUB2 分析 (一)

    GRUB是目前较流行启动引导程序.其第二版被主流Linux发行版所包括.本文将探索和分析GRUB的设计和实现机制. boot.S是第一个研究对象,因为boot.S将被编译成boot.img(512字节 ...

  4. spark + yarn调试问题java.nio.channels.ClosedChannelException

    spark客户端提交任务至yarn,后台抛错,FinalStatus:UNDEFINED. ./spark-submit  --class org.apache.spark.examples.Spar ...

  5. Codeforces 235C. Cyclical Quest

    传送门 写的时候挺蛋疼的. 刚开始的时候思路没跑偏,无非就是建个SAM然后把串开两倍然后在SAM上跑完后统计贡献.但是卡在第二个样例上就是没考虑相同的情况. 然后开始乱搞,发现会出现相同串的只有可能是 ...

  6. 20145327 《Java程序设计》第二周学习总结

    20145327 <Java程序设计>第二周学习总结 教材学习内容总结 JAVA类型:基本类型与类类型(也称参考类型). 基本类型分为:整数(short,int,long).字节(byte ...

  7. mybatis关联配置(一对多配置)

    敲代码也有不少日子了,今天碰到个需求,就是定时器生成一张表,但是这个表的某些数据是从另外两张表中拿到的,定外两张表又是一对多的关系,想着咋在一个接口就能敲出来,大概结构如下 然后需要a表的数据(比如张 ...

  8. Jquery14 工具函数

    学习要点: 1.字符串操作 2.数组和对象操作 3.测试操作 4.URL 操作 5.浏览器检测 6.其他操作 工具函数是指直接依附于 jQuery 对象,针对 jQuery 对象本身定义的方法,即全局 ...

  9. db2 xml 转 table

    版本:DB2 Version 9.1 1.创建测试表,初始化数据 create table emp (doc XML); INSERT INTO EMP VALUES ('<dept bldg= ...

  10. POJ_1159 Palindrome (线性动态规划+滚动数组)

    题意是说,给定一个字符串,问至少还需要插入多少个字符才能使得该字符串成为回文字符串. 这道题一开始做的时候用了一个简单的动态规划,开了一个5000*5000的数组,用递归形式实现,代码如下: 其中d[ ...