1. 程式人生 > >Codeforces Round #528 (Div. 2, based on Technocup 2019 Elimination Round 4)題解

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題太難補不動。溜了溜了