每日一题 day39 打卡

Analysis

1.当正向思考受阻时,逆向思维可能有奇效。

2.问题转化为:找到最小的d,使去掉所有权值>d的边之后,连通支的个数<k;

3.定理:如果去掉所有权值>d的边之后,最小生成树被分割为k个连通支,则图也被分为k个连通支。

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 #include<cmath>
 6 #define maxn 10000000+10
 7 #define INF 9187201950435737471
 8 #define rep(i,s,e) for(register int i=s;i<=e;++i)
 9 #define dwn(i,s,e) for(register int i=s;i>=e;--i)
10 using namespace std;
11 inline int read()
12 {
13     int x=0;
14     bool f=1;
15     char c=getchar();
16     for(; !isdigit(c); c=getchar()) if(c=='-') f=0;
17     for(; isdigit(c); c=getchar()) x=(x<<3)+(x<<1)+c-'0';
18     if(f) return x;
19     return 0-x;
20 }
21 inline void write(int x)
22 {
23     if(x<0){putchar('-');x=-x;}
24     if(x>9)write(x/10);
25     putchar(x%10+'0');
26 }
27 int n,k,cnt,tot;
28 int f[maxn];
29 double ans[maxn];
30 struct node1
31 {
32     int x,y;
33 }coo[maxn];
34 struct node2
35 {
36     int xx,yy;
37     double dis;
38 }tree[maxn];
39 inline double calc(int x_,int y_,int x__,int y__)
40 {
41     return sqrt(((double)x_-(double)x__)*((double)x_-(double)x__)+((double)y_-(double)y__)*((double)y_-(double)y__));
42 }
43 inline int find(int x)
44 {
45     if(f[x]==x) return x;
46     return f[x]=find(f[x]);
47 }
48 bool cmp(node2 x,node2 y)
49 {
50     return x.dis<y.dis;
51 }
52 signed main()
53 {
54     rep(i,1,1000) f[i]=i;
55     n=read();k=read();
56     rep(i,1,n) coo[i].x=read(),coo[i].y=read();
57     rep(i,1,n)
58         rep(j,i+1,n)
59         {
60             tree[++cnt].xx=i;
61             tree[cnt].yy=j;
62             tree[cnt].dis=calc(coo[i].x,coo[i].y,coo[j].x,coo[j].y);
63         }
64     sort(tree+1,tree+cnt+1,cmp);
65     rep(i,1,cnt)
66     {
67         int f1=find(tree[i].xx);
68         int f2=find(tree[i].yy);
69         if(f1!=f2)
70         {
71             f[f1]=f2;
72             ans[++tot]=tree[i].dis;
73             if(tot==n-1) break;
74         }
75     }
76     printf("%.2lf",ans[tot-k+1]);
77     return 0;
78 }

请各位大佬斧正

01-16 15:18