hdu Portal(离线,并查集)

题意:在一张无向图上,已知边权,做q组询问,问小于L的点对共有几组。点对间的距离取=min(两点之间每一条通路上的最大值)。

分析:这里取最大值的最小值,常用到二分。而这里利用离线算法,先对边从小到大排序,逐一加入集合中。利用并查集,当两点之间不在同一个集合,那么所加入的边就是两个集合中任一点对的距离(两集合各取一点)。所以有cnt2+=num[fu]*num[fv];

注意:有些询问比m条边中的最小边还小,比最大边还大。

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 using namespace std;
 5 
 6 const int MAXN=11111;
 7 
 8 struct Edge{
 9     int u,v,c;
10 }edge[5*MAXN];
11 
12 struct Query{
13     int sq,id;
14 }query[MAXN];
15 
16 int num[MAXN],ans[MAXN];
17 int f[MAXN];
18 
19 int cmp1(Edge a,Edge b)
20 {
21     return a.c<b.c;
22 }
23 
24 int cmp2(Query a,Query b)
25 {
26     return a.sq<b.sq;
27 }
28 
29 void init(int n)
30 {
31     for(int i=1;i<=n;i++)
32     {
33         num[i]=1;
34         f[i]=i;
35     }
36 }
37 
38 int find(int x)
39 {
40     return f[x]==x?x:f[x]=find(f[x]);
41 }
42 
43 int main()
44 {
45     int n,m,q;
46     while(~scanf("%d%d%d",&n,&m,&q))
47     {
48         for(int i=0;i<m;i++)
49             scanf("%d%d%d",&edge[i].u,&edge[i].v,&edge[i].c);
50         sort(edge,edge+m,cmp1);
51 
52         for(int i=0;i<q;i++)
53         {
54             scanf("%d",&query[i].sq);
55             query[i].id=i;
56         }
57         sort(query,query+q,cmp2);
58 
59         init(n);
60         int cnt1,cnt2,tol=0;
61         cnt1=cnt2=0;
62         for(int i=0;i<m;i++)
63         {
64             int u=edge[i].u;
65             int v=edge[i].v;
66             int c=edge[i].c;
67 
68             int fu=find(u);
69             int fv=find(v);
70 
71             if(fu==fv)//在同一集合不影响
72                 continue;
73 
74             cnt1=cnt2;//记录上一个值
75             cnt2+=num[fu]*num[fv];
76             
77             f[fv]=fu;
78             num[fu]+=num[fv];//注意这两步处理要相同
79 
80             while(c>query[tol].sq)//取cnt1更新询问
81             {
82                 ans[query[tol].id]=cnt1;
83                 tol++;
84             }
85         }
86         while(tol<q)//把大于最大边的询问统一处理成cnt2
87         {
88             ans[query[tol].id]=cnt2;
89             tol++;
90         }
91         for(int i=0;i<q;i++)
92             printf("%d\n",ans[i]);
93     }
94     return 0;
95 }
View Code

posted @ 2013-10-20 14:46  Thousand Sunny  阅读(403)  评论(0编辑  收藏  举报