n个点m条无向边的图,对于q个询问,每次查询点对间最小瓶颈路 >=f 的点对有多少。

最小瓶颈路显然在kruskal求得的MST上。而输入保证所有边权唯一,也就是说f[i][j]肯定唯一了。

拿到这题第一反映是用次小生成树的prim算法在求MST的同时求出每对点对的瓶颈路。几乎就是一个模板题,无奈却MLE。。。

于是换算法,用kruskal求MST,然后对于MST,离线LCA求出所有点对的瓶颈路。同UVA 11354 Bond(MST + LCA)然后剩下的就是读入&二分查找输出了。。无奈还是MLE!!!

最后。。。反思了一下。。。在kruskal的过程,当前加入的边必定是新图中最大的边!也就是说,每次加入一条边,求出当前图中经过该边的点对数就行了。。。求一个图中经过该边的点对数,将该边割开,分别从两个端点dfs,左边能遍历到x个点,右边能遍历到y个点,那么点对数就是x*y了。

原图不连通的情况也是存在的吧,这个几乎对算法不影响,只需在进入MST的点数==n的时候终止函数就行了。

#include<algorithm>
#include<iostream>
#include<cstring>
#include<fstream>
#include<sstream>
#include<vector>
#include<string>
#include<cstdio>
#include<bitset>
#include<queue>
#include<stack>
#include<cmath>
#include<map>
#include<set>
#define FF(i, a, b) for(int i=a; i<b; i++)
#define FD(i, a, b) for(int i=a; i>=b; i--)
#define REP(i, n) for(int i=0; i<n; i++)
#define CLR(a, b) memset(a, b, sizeof(a))
#define LL long long
#define PB push_back
#define eps 1e-10
#define debug puts("**debug**")
using namespace std; const int maxn = 10010;
const int maxm = 555555;
const int INF = 1e9;
int n, m, dfs_clock, q, f, cnt, fa[maxn];
LL sum[maxn*2];
bool seen[maxn];
vector<int> edge; struct E
{
int u, v, w;
E(){}
E(int u, int v, int w) : u(u), v(v), w(w){}
bool operator < (const E& rhs) const
{
return w < rhs.w;
}
}e[maxm]; //kruskal的边 vector<int> G[maxn]; //dfs用
inline void add(int a, int b)
{
G[a].PB(b);
G[b].PB(a);
} int findset(int x) { return x == fa[x] ? x : fa[x] = findset(fa[x]); } void dfs(int u, int fa)
{
dfs_clock++;
REP(i, G[u].size())
{
int v = G[u][i];
if(v != fa) dfs(v, u);
}
} void MST()
{
int ret = 0;
cnt = 1;
sum[0] = 0;
CLR(seen, 0);
sort(e, e+m); REP(i, m)
{
int x = findset(e[i].u), y = findset(e[i].v);
if(x != y)
{
//统计进入森林的点数
if(!seen[e[i].u]) ret++;
if(!seen[e[i].v]) ret++;
seen[e[i].u] = 1;
seen[e[i].v] = 1; fa[x] = y;
add(e[i].u, e[i].v); //将边切割双向统计两边点数
dfs_clock = 0;
dfs(e[i].u, e[i].v);
int a = dfs_clock; dfs_clock = 0;
dfs(e[i].v, e[i].u);
int b = dfs_clock; //edge保存所有MST中边 sum[i]为前i条边和
edge.PB(e[i].w);
sum[cnt] = sum[cnt-1] + a*b;
cnt++;
}
if(ret == n) return ; //终止MST
}
return ;
} void solve()
{
scanf("%d", &q);
while(q--)
{
scanf("%d", &f);
int t = lower_bound(edge.begin(), edge.end(), f) - edge.begin();
//找到f的lower_bound 答案便是总和减去小于f的点对和 注意乘以2
printf("%lld\n", (sum[cnt-1]-sum[t])*2);
}
} int main()
{
while(~scanf("%d%d", &n, &m))
{
REP(i, n) G[i].clear(), fa[i] = i;
edge.clear();
REP(i, m)
scanf("%d%d%d", &e[i].u, &e[i].v, &e[i].w); MST(); solve(); }
return 0;
}

hdu 4750 Count The Pairs (2013南京网络赛)的更多相关文章

  1. HDU 4751 Divide Groups (2013南京网络赛1004题,判断二分图)

    Divide Groups Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Tot ...

  2. HDU 4750 Count The Pairs (2013南京网络赛1003题,并查集)

    Count The Pairs Time Limit: 20000/10000 MS (Java/Others)    Memory Limit: 65535/65535 K (Java/Others ...

  3. HDU 4758 Walk Through Squares (2013南京网络赛1011题,AC自动机+DP)

    Walk Through Squares Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65535/65535 K (Java/Oth ...

  4. HDU 4759 Poker Shuffle(2013长春网络赛1001题)

    Poker Shuffle Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Tot ...

  5. HDU 4763 Theme Section (2013长春网络赛1005,KMP)

    Theme Section Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Tot ...

  6. HDU 4745 Two Rabbits (2013杭州网络赛1008,最长回文子串)

    Two Rabbits Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65535/65535 K (Java/Others)Tota ...

  7. HDU 4734 F(x) (2013成都网络赛,数位DP)

    F(x) Time Limit: 1000/500 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submiss ...

  8. HDU 4731 Minimum palindrome (2013成都网络赛,找规律构造)

    Minimum palindrome Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Other ...

  9. 2013南京网赛1003 hdu 4750 Count The Pairs

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4750 题意:给出一个无向图,f(a,b)表示从点a到点b的所有路径中的每条路径的最长边中的最小值,给出 ...

随机推荐

  1. java项目获取路径的几种方式

    第一种: File f = new File(this.getClass().getResource("/").getPath()); System.out.println(f); ...

  2. html和css实现一级菜单和二级菜单学习笔记

    实现一级菜单: <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> ...

  3. Java第一周总结(20160801-20160807)

    day01: 1.常见的dos命令:    盘符:            进入指定的盘下面. 操作文件夹:         dir              列出当前控制台所在的路径下的所有文件以及文 ...

  4. StackOverflow程序员推荐:每个程序员都应读的30本书

    “如果能时光倒流,回到过去,作为一个开发人员,你可以告诉自己在职业生涯初期应该读一本,你会选择哪本书呢?我希望这个书单列表内容丰富,可以涵盖很多东西.” 很多程序员响应,他们在推荐时也写下自己的评语. ...

  5. vim常用指令一览

    插入指令 i 在光标处插入字符 I 在光标所在行最前插入 a 在光标所在字符后面插入 A 在光标所在行的最后插入 o 在光表所在行下面插入一行 O 在光标所在行上面插入一行 r 替换光标所在字符,只替 ...

  6. 关于Android Assets读取文件为File对象

    关于Android Assets读取文件为File对象的问题,在Assets里面放置文件,在使用的时候,一般是使用AssetManger对象,open方法获取InputStream 然后进行其他操作. ...

  7. cobbler之详细配置

    目录 作用 组件 命令 安装过程     安装包     配置文件     启动cobbler服务     配置cobbler服务     使用cobbler_web 作用:系统自动化安装,支持lin ...

  8. iptables中规则的关系——以只允许某些IP段访问为例

    最近遇到一个问题:服务器被全球的IP频繁试图通过ssh登录. 于是想到通过iptables防火墙限制访问,达到:仅允许指定ip段访问ssh服务(22端口). 关于iptables添加规则的文章有很多, ...

  9. 阿里巴巴JAVA常考面试题及汇总答案

    一.String,StringBuffer, StringBuilder 的区别是什么?String为什么是不可变的? 答:   1.String是字符串常量,StringBuffer和StringB ...

  10. 异常处理与调试4 - 零基础入门学习Delphi53

    调试(Debug) 让编程改变世界 Change the world by program 调试(Debug) 在应用程序开发中检测.处理程序中的错误是一个非常重要的环节.在Delphi的集成开发环境 ...