Codeforces Round #528 (Div. 2, based on Technocup 2019 Elimination Round 4)题解

2018-12-24晚小上一波分,这套比赛差点翻车,还好最后15分钟弄出了C,交C的

时候心里一点底都没有,因为C的情况可能超过我的想象,现在看来我的担心是不

必要的。。。然后倒数20多秒绝杀了D题。。这道题很有自信样例都没测直接交果

然也过了,后面的题目都没时间来得及看。。。赛后补好了。

A题和B题太水了不写题解。。

 

C. Connect Three

题意:

平面上有A,B,C三个点,用最短的路径连接它们,输出最短路径长度、最短路径(任意顺序输出均可)。

思路:

容易发现最短路径长度是最高点-最低点+最右点-最左点+1,麻烦在于怎么输出路径。

这道题情况很多,直接模拟每种情况可以写但是比较麻烦,这里介绍一下我的方法。如下图所示,

我们可以按照x从小到大排下序,然后确定一下他们的汇合点,这个汇合点D的坐标Dx=Bx,Dy=Cy;

然后我们可以分别从A,B,C出发连到D去,连的时候记得对走过的路径打上标记就ojbk了。

代码:

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 typedef long long ll;
 4 struct node{
 5     int x,y;
 6 }a[10];
 7 bool cmp(node a,node b){
 8     return a.x<b.x;
 9 }
10 bool cmp1(node a,node b){
11     return a.y<b.y;
12 }
13 int vis[1005][1005];
14 int main(){
15     cin>>a[1].x>>a[1].y>>a[2].x>>a[2].y>>a[3].x>>a[3].y;
16     sort(a+1,a+4,cmp);
17     int l=9999,r=0,u=0,d=9999;
18     for(int i=1;i<=3;i++){
19         l=min(l,a[i].y);
20         r=max(r,a[i].y);
21         u=max(u,a[i].x);
22         d=min(d,a[i].x);
23     }
24     //printf("%d %d %d %d\n",l,r,d,u);
25     int ans=r-l+u-d+1;
26     printf("%d\n",ans);
27     int x=a[2].x;
28     sort(a+1,a+4,cmp1);
29     int y=a[2].y;
30     for(int i=1;i<=3;i++){
31         if(x==a[i].x){    //输出B到D的路径
32             int s=a[i].y;
33             int e=y;
34             if(s>e)swap(s,e);
35             for(int j=s;j<=e;j++){
36                 if(!vis[x][j]){
37                     vis[x][j]=1;
38                     printf("%d %d\n",x,j);
39                 }
40             }
41         }
42         else if(y==a[i].y){ //输出C到D的路径
43             int s=a[i].x;
44             int e=x;
45             if(s>e)swap(s,e);
46             for(int j=s;j<=e;j++){
47                 if(!vis[j][y]){
48                     vis[j][y]=1;
49                     printf("%d %d\n",j,y);
50                 }
51             }
52         }
53         else{    //输出A到D的路径
54             int s=a[i].x;
55             int e=x;
56             if(s>e)swap(s,e);
57             for(int j=s;j<=e;j++){
58                 if(!vis[j][y]){
59                     vis[j][y]=1;
60                     printf("%d %d\n",j,y);
61                 }
62             }
63             s=a[i].y;
64             e=y;
65             if(s>e)swap(s,e);
66             for(int j=s;j<=e;j++){
67                 if(!vis[a[i].x][j]){
68                     vis[a[i].x][j]=1;
69                     printf("%d %d\n",a[i].x,j);
70                 }
71             }
72         }
73     }
74 }

D. Minimum Diameter Tree

题意:

给你一棵有n个节点的树,再给你一个s,构造这棵数的边权让他们的和加起来等于s,

求这棵树的最短直径,最短直径定义为树上任意两个节点的距离的最大值。

思路:

看样例容易看出答案跟叶子节点的个数有关,ans=s*2/叶子节点个数。

为什么呢?我们按照贪心来想,当把s全给平均分配给叶子节点的时候肯定是最优的,证毕。

代码:

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 typedef long long ll;
 4 vector<int>g[100005];
 5 int ans=0;
 6 void dfs(int u,int fa){
 7     if(g[u].size()==1){
 8         ans++;
 9         if(u!=1)return;
10     }
11     for(int i=0;i<g[u].size();i++){
12         int v=g[u][i];
13         if(v==fa)continue;
14         dfs(v,u);
15     }
16 }
17 int main(){
18     int n;
19     double s;
20     scanf("%d%lf",&n,&s);
21     for(int i=1;i<n;i++){
22         int x,y;
23         scanf("%d%d",&x,&y);
24         g[x].push_back(y);
25         g[y].push_back(x);
26     }
27     dfs(1,1);
28     double res=s/ans*2;
29     printf("%.18lf\n",res);
30 }

E、F题太难补不动。溜了溜了

猜你喜欢

转载自www.cnblogs.com/ccsu-kid/p/10166947.html