[JSOI2010]部落划分 最小生成树
链接
https://www.luogu.com.cn/problem/P4047
分析
这题其实不是很难,当时我是蒙过的。。。。。我本来输出的建到总数减部落数的边的距离,后来发现样例不对,调试了一下发现加上一正好能过,于是就加了一,没想到A了。
现在想想为什么要加一呢,其实很简单,构成k个部落,就是建出k个树,这样的话加入n-k条边就行,现在输出这条边的值是不行的,这条边是在同一个部落里边的,而要求的是两个不同部落间的距离,因为我们跑kruskal的时候是按照边从小到大加的边,所以这个时候下个一加进去的边就一定是两个距离最近的部落,往后的边都不小于这个边,于是这时输出就行。
1 #include<cstdio> 2 #include<algorithm> 3 #include<cstring> 4 #include<cmath> 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<i;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 }
int - > long long
0 - > 100