题意

给定一个无向图(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. HTML5游戏开发系列教程5(译)

    原文地址:http://www.script-tutorials.com/html5-game-development-lesson-5/ 最终我决定准备下一篇游戏开发系列的文章,我们将继续使用can ...

  2. Web 框架 Flask

    Flask是一个基于Python开发并且依赖jinja2模板和Werkzeug WSGI服务的一个微型框架,对于Werkzeug本质是Socket服务端,其用于接收http请求并对请求进行预处理,然后 ...

  3. Django restful Framework 之序列化与反序列化

    1. 首先在已建好的工程目录下新建app命名为snippets,并将snippets app以及rest_framework app加到工程目录的 INSTALLED_APPS 中去,具体如下: IN ...

  4. Appium移动自动化

    一. 安装node.js 因为Appium是使用nodejs实现的,所以node是解释器,首先需要确认安装好 官网下载node.js:https://nodejs.org/en/download/ 安 ...

  5. Linux远程管理器xshell和xftp使用教程,以及遇到关闭Xshell后项目也停止的解决方法

    1.xshell 是一个强大的安全终端模拟软件,它支持SSH1, SSH2, 以及Microsoft Windows 平台的TELNET 协议. 2.是一个基于 MS windows 平台的功能强大的 ...

  6. mspdb100.dll不见了的解决办法

    一.如果在运行某软件或编译程序时提示缺少.找不到mspdb100.dll等类似提示,将下载来的mspdb100.dll拷贝到指定目录即可 (一般是system系统目录或放到软件同级目录里面),或者重新 ...

  7. 20145312 《Java程序设计》第六周学习总结

    20145312 <Java程序设计>第六周学习总结 学习笔记 Chapter10 输入 /输出 10.1InputStream 与 OutputStream 10.1.1 串流设计的概念 ...

  8. HelloWorld程序编写调试及错误解决

    HelloWorld程序编写调试及错误解决 eclipse软件编写 相较于windows内置记事本,eclipse编写程序更为简单快捷.由其生成的程序模板编写如下: package helloworl ...

  9. DVWA安装

    DVWA安装: 启动xampp下的apache中间件和mysql 将dvwa放到xampp下的htdocs目录下 在浏览器输入http://127.0.0.1/dvwa 即可使用啦! 还有owasp的 ...

  10. Vue.js项目部署在Tomcat服务器上

    1.在本地的Vue框架中 执行npm run build  将我们的项目打包到dist 文件夹中 2.在服务器上的Tomcat的 webapps文件夹下,新建一个文件夹如:frontvue 3.启动t ...