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 ...
随机推荐
- SQL Server返回插入数据的ID和受影响的行数
首先看看数据库里面的数据(S_Id为自增长标识列): sql server 中返回上一次插入数据的ID(标识值)有三种方式: 第一种 @@IDENTITY: insert into Student(S ...
- 技术分享会(二):SQLSERVER索引介绍
SQLSERVER索引介绍 一.SQLSERVER索引类型? 1.聚集索引: 2.非聚集索引: 3.包含索引: 4.列存储索引: 5.无索引(堆表): 二.如何创建索引? 索引示例: 建表 creat ...
- Log4net 自定义字段 写入Oracle 使用ODP.NET Managed驱动
一.环境说明: 开发工具:vs2010 ,数据库:oracle 11g ,版本:log4net的目前最新版本1.2.13.0 : Oracle.ManagedDataAccess.dll ...
- dev-server.js详解
转载自:https://www.cnblogs.com/ye-hcj/p/7091706.html dev-server.js详解 require('./check-versions')() var ...
- 受限的用户shell环境
有些特殊情况下需要实现将系统内普通用户限定在指定目录下,并且只能使用系统管理员设定的命令.lshell就是实现这样功能的一个神器. lshell提供了一个针对每个用户可配置的限制性shell,lshe ...
- 使用CXF+Spring发布WebService,启动报错
使用CXF+Spring发布WebService,启动报错,日志如下: 五月 12, 2017 9:01:37 下午 org.apache.tomcat.util.digester.SetProper ...
- 前端使用canvas绘制立体三角形
前端绘制立体效果的三角形的demo 在移动端使用时,需要自适应屏幕.canvas上无法设置rem,所以在canvas外加一个父级元素设置为rem,再将canvas的宽高设置为100% 100%. 如果 ...
- 3.1、Ubuntu系统中jmeter的安装和目录解析
以下内容亲测,如果不对的地方,欢迎留言指正,不甚感激.^_^祝工作愉快^_^ Jmeter是一个非常好用的压力测试工具. Jmeter用来做轻量级的压力测试,非常合适,只需要十几分钟,就能把压力测 ...
- 20145216史婧瑶《Java程序设计》第10周学习总结
20145216 <Java程序设计>第10周学习总结 教材学习内容总结 网络编程 一.网络概述 网络编程就是两个或多个设备(程序)之间的数据交换. 识别网络上的每个设备:①IP地址②域名 ...
- 图片上传oss--先拿server端签名再上传oss,返回id值
目前项目oss阿里云存储图片,图片上传主要步骤是:前端从服务端拿到签名signature,再上传到oss上busket里,上传成功返回图片id (imgId),最后再给server端: 注:官网上有个 ...