2013南京网赛1003 hdu 4750 Count The Pairs

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4750

题意:给出一个无向图,f(a,b)表示从点a到点b的所有路径中的每条路径的最长边中的最小值,给出 p个询问,每个询问有一个数t,对于每个询问,求有多少对顶点f(a,b)小于t。注意(1,2)和(2,1)是不同的点对

分析:

正过来想不太好做..反过来..看在当前t的限制下..有多少个点对f(u,v)<t...这样答案就是totol-sum...totol是总对数n*(n-1)...sum是当前可联通的..

这样转化后就不难想到将所有的询问从小到大排序..将所有的边从小到大排序..然后根据递增的询问不断地加边统计答案..而要统计答案和维护图的联通关系时用到并查集....如此时间复杂度为O(m).有点像模拟最小生成树的Kurskal

对于每一条边(a,b),判断两个端点a,b是否属于同一个集合,如果不是,则当前边就是a,b所有路径中要求的“瓶颈边”(因为所有的边是从小到大排序的),这时小于t的点对数为sum加上这两个集合的顶点点个数乘积的两倍,即sum+=num[f1]*num[f2]*2,最后对于每个询问输出total-sum即可。

AC代码如下:

 1 #include<stdio.h>
 2 #include<string.h>
 3 #include<algorithm>
 4 using namespace std;
 5 struct NODE
 6 {
 7     int u,v,w;
 8     bool operator <(const NODE &a)const{
 9         return w<a.w;
10     }
11 }node[500005];
12 struct T
13 {
14     int d,id;
15     bool operator <(const T &a)const{
16         return d<a.d;
17     }
18 }t[100005];
19 int num[10005],fa[10005],ans[100005];
20 int find(int x)
21 {
22     if(x!=fa[x])
23         fa[x]=find(fa[x]);
24     return fa[x];
25 }
26 int main()
27 {
28     int n,m,j,i,p;
29     while(scanf("%d%d",&n,&m)!=EOF)
30     {
31         for(i=0;i<m;i++)
32             scanf("%d%d%d",&node[i].u,&node[i].v,&node[i].w);
33         scanf("%d",&p);
34         for(i=0;i<p;i++)
35         {
36             scanf("%d",&t[i].d);
37             t[i].id=i;
38         }
39         sort(node,node+m);
40         sort(t,t+p);
41         for(i=0;i<n;i++)
42         {
43             fa[i]=i;
44             num[i]=1;
45         }
46         int total=n*(n-1);
47         int sum=0;
48         j=0;
49         for(i=0;i<p;i++)
50         {
51             while(j<m&&node[j].w<t[i].d)
52             {
53                 int f1=find(node[j].u);
54                 int f2=find(node[j].v);
55                 if(f1==f2)
56                 {
57                     j++;
58                     continue;
59                 }
60                 sum+=num[f1]*num[f2]*2;
61                 fa[f1]=f2;
62                 num[f2]+=num[f1];
63                 j++;
64             }
65             ans[t[i].id]=total-sum;
66         }
67         for(i=0;i<p;i++)
68             printf("%d\n",ans[i]);
69     }
70     return 0;
71 }
View Code

 

posted on 2013-09-23 19:20  jumpingfrog0  阅读(328)  评论(0编辑  收藏  举报

导航