这题太水了吧,不知道怎么蓝的,蒟蒻只写了十五分钟就一次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吧~