hdu 4750 Count The Pairs(并查集+二分)

Problem Description

  
With the 60th anniversary celebration of Nanjing University of Science and Technology coming soon, the university sets n tourist spots to welcome guests. Of course, Redwood forests in our university and its Orychophragmus violaceus must be recommended as top ten tourist spots, probably the best of all. Some undirected roads are made to connect pairs of tourist spots. For example, from Redwood forests (suppose it’s a) to fountain plaza (suppose it’s b), there may exist an undirected road with its length c. By the way, there is m roads totally here. Accidently, these roads’ length is an integer, and all of them are different. Some of these spots can reach directly or indirectly to some other spots. For guests, they are travelling from tourist spot s to tourist spot t, they can achieve some value f. According to the statistics calculated and recorded by us in last years, We found a strange way to calculate the value f:
  From s to t, there may exist lots of different paths, guests will try every one of them. One particular path is consisted of some undirected roads. When they are travelling in this path, they will try to remember the value of longest road in this path. In the end, guests will remember too many longest roads’ value, so he cannot catch them all. But, one thing which guests will keep it in mind is that the minimal number of all these longest values. And value f is exactly the same with the minimal number.
  Tom200 will recommend pairs (s, t) (start spot, end spot points pair) to guests. P guests will come to visit our university, and every one of them has a requirement for value f, satisfying f>=t. Tom200 needs your help. For each requirement, how many pairs (s, t) you can offer?
 
Input
  
Multiple cases, end with EOF.
  First line:n m
  n tourist spots ( 1<n<=10000), spots’ index starts from 0.
  m undirected roads ( 1<m<=500000).

  Next m lines, 3 integers, a b c
  From tourist spot a to tourist spot b, its length is c. 0<a, b<n, c(0<c<1000000000), all c are different.

  Next one line, 1 integer, p (0<p<=100000)
  It means p guests coming.

  Next p line, each line one integer, t(0<=t)
  The value t you need to consider to satisfy f>=t.
 
Output
 
 For each guest's requirement value t, output the number of pairs satisfying f>=t.
  Notice, (1,2), (2,1) are different pairs.
 
Sample Input
2 1
0 1 2
3
1
2
3
3 3
0 1 2
0 2 4
1 2 5
5
0 
2
3
4
5
 
Sample Output
2
2
0
6
6
4
4
0
 
Source
 
 

题目大意:

给一无向图,n个点,m条边,每条边有个长度,且不一样。定义f(i,j)表示从节点i到节点j的所有路径中的最大边权值的最小值。有q个询问,每个询问有个t,求f(i,j)>=t的种数。

解题思路:

并查集+简单dp+二分。

思路,先按边从小到大排序考虑,对于每条边E该边两个节点为a、b,如果a、b不在同一个联通块,则a联通块中点集A和b联通块中点集B的f值一定为E(因为E升序)。恰好能使其通路。

map[i]表示以权值为i的边作为f值的点对个数。

sum[i]表示以大于等于第i大边权值的权值作为f值得点对总的个数。

对于每一个t,在排序了的sig[i](能取的边权值)中二分找到大于等于它的最小的小标j。输出sum[j]即可。

注意:

求点对个数时要乘以2.

 1 #pragma comment(linker, "/STACK:1024000000,1024000000")
 2 #include<iostream>
 3 #include<cstdio>
 4 #include<cstring>
 5 #include<cmath>
 6 #include<math.h>
 7 #include<algorithm>
 8 #include<queue>
 9 #include<set>
10 #include<bitset>
11 #include<map>
12 #include<vector>
13 #include<stdlib.h>
14 #include <stack>
15 using namespace std;
16 #define PI acos(-1.0)
17 #define max(a,b) (a) > (b) ? (a) : (b)  
18 #define min(a,b) (a) < (b) ? (a) : (b)
19 #define ll long long
20 #define eps 1e-10
21 #define MOD 1000000007
22 #define N 10006
23 #define M 600000
24 #define inf 1e12
25 int n,m;
26 struct Node{
27     int x,y;
28     int cost;
29 }node[M];
30 ////////////////////////////////////////////////////
31 int fa[N];
32 int cnt[N];
33 void init(){
34     for(int i=0;i<N;i++){
35         fa[i]=i;
36         cnt[i]=1;
37     }
38 }
39 int find(int x){
40     return fa[x]==x?x:fa[x]=find(fa[x]);
41 }
42 
43 //////////////////////////////////////////////////////
44 bool cmp(Node a,Node b){
45     return a.cost<b.cost;
46 }
47 ////////////////////////////////////////////
48 int a[M];
49 int b[M];
50 int sum[M];
51 int main()
52 {
53     while(scanf("%d%d",&n,&m)==2){
54         
55         for(int i=0;i<m;i++){
56             scanf("%d%d%d",&node[i].x,&node[i].y,&node[i].cost);
57         
58         }
59         sort(node,node+m,cmp);
60         
61         for(int i=0;i<m;i++){
62             b[i]=node[i].cost;
63         }
64         
65         memset(a,0,sizeof(a));
66         
67         init();
68         int ans=0;
69         for(int i=0;i<m;i++){
70               int root1=find(node[i].x);
71             int root2=find(node[i].y);
72             if(root1==root2) continue;
73             fa[root1]=root2;
74             //ans=ans+2*cnt[root1]*cnt[root2];
75             a[i]=2*cnt[root1]*cnt[root2];
76             cnt[root2]+=cnt[root1];
77                     
78         }
79         
80         memset(sum,0,sizeof(sum));
81         for(int i=m-1;i>=0;i--){
82             sum[i]=sum[i+1]+a[i];
83         }
84         
85         int q;
86         scanf("%d",&q);
87         while(q--){
88             int t;
89             scanf("%d",&t);
90             int w=lower_bound(b,b+m,t)-b;
91             printf("%d
",sum[w]);
92         }
93         
94     }
95     return 0;
96 }
View Code
原文地址:https://www.cnblogs.com/UniqueColor/p/4815825.html