这题太水了吧,不知道怎么蓝的,蒟蒻只写了十五分钟就一次AC了……
但是挺有意思,就发篇题解吧qwq
emmm……最小生成树(贪心),就没别的了……
要明确:
一开始可以把每个点都看成一个部落,那么每一次连一条不相通的边时,就相当于合并了两个部落。
那么当剩下k个部落的时候,找下一条边即可。
有一个要注意:
就是当已经找完所有边时,不能直接输出第i+1条,而是要继续找直到找到下一条合法边(原因很简单,就不解释了……)
代码代码:
#include<cstdio> #include<algorithm> #include<iostream> #include<cmath> using namespace std; #define maxn 1000005 //#define int double int n,k,cnt; int nx[1005],ny[1005],par[maxn]; struct node { int from,to; double w; } q[maxn]; bool cmp(node a,node b) { return a.w<b.w; } double use(int x,int y,int xx,int yy) { return sqrt( pow(x-xx,2)+pow(y-yy,2) ); } void add(int x,int y,double e) { q[++cnt].to=y; q[cnt].from=x; q[cnt].w=e; } int find(int x) { return x==par[x] ? x : par[x]=find(par[x]); } void merge(int x,int y) { par[find(y)]=find(x); } void kruskal() { for(int i=1;i<=cnt;i++) { int nowx=q[i].from,nowy=q[i].to; if(find(nowx)==find(nowy)) continue; merge(nowx,nowy); n--; if(n==k-1) { printf("%.2lf",q[i].w); break; } } } main() { scanf("%d%d",&n,&k); for(int i=1;i<=n;i++) par[i]=i; for(int i=1;i<=n;i++) scanf("%d%d",&nx[i],&ny[i]); for(int i=1;i<=n;i++) for(int j=1;j<i;j++) { double e=use(nx[i],ny[i],nx[j],ny[j]); add(i,j,e); add(j,i,e); } sort(q+1,q+cnt+1,cmp); kruskal(); return 0; }
这么简单的题要不去直接AC吧~