[JSOI2010]部落划分 最小生成树

链接

https://www.luogu.com.cn/problem/P4047

分析

  这题其实不是很难,当时我是蒙过的。。。。。我本来输出的建到总数减部落数的边的距离,后来发现样例不对,调试了一下发现加上一正好能过,于是就加了一,没想到A了。

  现在想想为什么要加一呢,其实很简单,构成k个部落,就是建出k个树,这样的话加入n-k条边就行,现在输出这条边的值是不行的,这条边是在同一个部落里边的,而要求的是两个不同部落间的距离,因为我们跑kruskal的时候是按照边从小到大加的边,所以这个时候下个一加进去的边就一定是两个距离最近的部落,往后的边都不小于这个边,于是这时输出就行。

 1 #include
 2 #include
 3 #include
 4 #include
 5 using namespace std;
 6 const int N=1e6;
 7 struct Node{
 8     int from,to;double val;
 9     bool operator < (const Node&A)const{
10         return val<A.val;
11     }
12 }B[N];
13 int m,n,q,t,s,len=0,f[N],x[N],y[N];
14 int find(int x){
15     return f[x]==x?f[x]:(f[x]=find(f[x]));
16 }
17 double dis(int a,int b,int c,int d){
18     return sqrt((a-c)*(a-c)+(b-d)*(b-d));
19 }
20 void kruskal(){
21     for(int i=1;i<=n;i++)f[i]=i;
22     sort(B+1,B+len+1);
23     int k=0;double ans=0;
24     for(int i=1;i<=len;i++){
25         int u=B[i].from,v=B[i].to;
26         if(find(u)!=find(v)){
27             f[find(u)]=find(v);
28             if(++k==n-q+1){
29                 printf("%.2lf\n",B[i].val);
30                 return;
31             }
32         }
33     }
34 }
35 int main(){
36 //    freopen("a.txt","r",stdin);
37     scanf("%d%d",&n,&q);
38     for(int i=1;i<=n;i++){
39         scanf("%d%d",&x[i],&y[i]);
40         for(int j=1;j){
41             B[++len].from=i,B[len].to=j;
42             B[len].val=dis(x[i],y[i],x[j],y[j]);
43         }
44     }
45     kruskal();
46     return 0; 
47 }

 

你可能感兴趣的:([JSOI2010]部落划分 最小生成树)