hdu 4750

参考阳神的博客写的,非常好的一个方法。

题目的意思是:

  对于每对点 找出他们之间所有路径中 最长边 的最小值~~~好拗口的!

思路:

  直接找出满足要求的太过于麻烦;所以找出不满足条件的,然后用总的数目(n*(n-1))减去不满足的就行;

做法:

  因为找的是最长边,所以首先将边和查询都按从小到大排好序。因为满足要满足条件,查询的值要比当前已经访问的边的值要大;

  另外,访问了边之后要维护,选用并查集!

感觉这个方法很正确,但是不会证明  = =!

代码:

 1 #include<cstdio>
 2 #include<algorithm>
 3 #define maxn 10005
 4 #define maxm 500005
 5 using namespace std;
 6 
 7 struct node
 8 {
 9     int from,to,w;
10     bool operator <(const node &t)const
11     {
12         return w<t.w;
13     }
14 } no[maxm];
15 
16 struct query
17 {
18     int id,w;
19     bool operator <(const query &t)const
20     {
21         return w<t.w;
22     }
23 } q[maxm];
24 
25 int f[maxn],ans[maxm],num[maxn];
26 
27 int find(int x)
28 {
29     int tmp=x;
30     while(x!=f[x]) x=f[x];
31     while(f[tmp]!=x)
32     {
33         int t=f[tmp];
34         f[tmp]=x;
35         tmp=t;
36     }
37     return x;
38 }
39 
40 int main()
41 {
42     int n,x,y,m,res,t,qq,tot;
43     while(scanf("%d%d",&n,&m)!=EOF)
44     {
45         for(int i=0;i<n;i++)f[i]=i,num[i]=1;
46         for(int i=1; i<=m; i++)scanf("%d%d%d",&no[i].from,&no[i].to,&no[i].w);
47         sort(no+1,no+m+1);
48         scanf("%d",&qq);
49         for(int i=0; i<qq; i++)scanf("%d",&q[i].w),q[i].id=i;
50         sort(q,q+qq);
51         res=0,t=1,tot=(n-1)*n;
52         for(int i=0; i<qq; i++)
53         {
54             int d=q[i].w;
55             while(t<=m&&no[t].w<d)
56             {
57                 x=find(no[t].from),y=find(no[t].to);
58                 if(x==y){t++;continue;}
59                 res+=num[x]*num[y]*2;
60                 num[y]+=num[x];
61                 f[x]=y;
62                 t++;
63             }
64             ans[q[i].id]=tot-res;
65         }
66         for(int i=0; i<qq; i++)printf("%d
",ans[i]);
67     }
68     return 0;
69 }
View Code
原文地址:https://www.cnblogs.com/yours1103/p/3335817.html