競賽題解 NOIP2018 賽道修建

2022-04-30 23:21:22 字數 3017 閱讀 9128

額……考試的時候大概猜到正解,但是時間不夠了,不敢寫,就寫了騙分qwq

現在把坑填好了~

(copy from 洛谷)

c 城將要舉辦一系列的賽車比賽。在比賽前,需要在城內修建 \(m\) 條賽道。

c 城一共有 \(n\) 個路口,這些路口編號為 \(1,2,...,n\),有 \(n-1\) 條適合於修建賽道的雙向通行的道路,每條道路連線著兩個路口。其中,第 \(i\) 條道路連線的兩個路口編號為 \(a_i\) 和 \(b_i\),該道路的長度為 \(l_i\) 。借助這 \(n-1\) 條道路,從任何乙個路口出發都能到達其他所有的路口。

一條賽道是一組互不相同的道路 \(e_1,e_2,…,e_k\),滿足可以從某個路口出發,依次經過 道路 \(e_1,e_2,…,e_k\)(每條道路經過一次,不允許調頭)到達另乙個路口。一條賽道的長度等於經過的各道路的長度之和。為保證安全,要求每條道路至多被一條賽道經過。

目前賽道修建的方案尚未確定。你的任務是設計一種賽道修建的方案,使得修建的 \(m\) 條賽道中長度最小的賽道長度最大(即 \(m\) 條賽道中最短賽道的長度盡可能大)

輸入格式:

輸入檔案第一行包含兩個由空格分隔的正整數 \(n,m\),分別表示路口數及需要修建的 賽道數。

接下來 \(n-1\) 行,第 ii 行包含三個正整數 \(a_i,b_i,l_i\) ,表示第 \(i\) 條適合於修建賽道的道 路連線的兩個路口編號及道路長度。保證任意兩個路口均可通過這 \(n-1\) 條道路相互到達。每行中相鄰兩數之間均由乙個空格分隔。

輸出格式:

輸出共一行,包含乙個整數,表示長度最小的賽道長度的最大值。

首先題目非常重要——這是乙個樹形結構,而且滿足單調性(即如果答案為x,則》x的值都不能符合條件,如果大家做了「菊花圖」(就是從乙個頂點伸出去很多條邊)的部分資料,就應該知道有乙個貪心的性質——對於乙個點u,如果連線 u 和 u的乙個兒子 的邊的長度大於等於答案,那就把這條邊割開,單獨形成一條路徑;接下來考慮長度比答案小的邊,那麼我們盡量地將長度大的邊與較小邊匹配形成一條路徑。這樣的話我們就可以寫出來一段**(ac的):

//edg是u與u的兒子的邊的長度(都不超過二分出來的答案)

sort(edg,edg+n);

int res=0;

for(int l=0,r=n;l=r) break;

res++; //新構成的路徑

l++;

}

我們不妨考慮每乙個點 u 及其兒子 v ——形成路徑的情況無非是①加上u->v[i]的邊形成乙個路徑;②加上u->v[i]和u->v[j]的邊形成乙個路徑;③加上u->v[i]的邊然後再與u的祖先相連。

不難想到我們可以把每棵子樹都看成乙個菊花圖做一次貪心。

但是有上述的情況③,這樣的話就不能直接看邊權了,我們可以讓 dp[u] 表示在點u的子樹以u為端點的路徑的長度。然後考慮子樹u中u的乙個兒子v,如果 dp[v]+(u->v的邊長) 滿足答案,就將已經構成的路徑個數cnt++;否則將 dp[v]+(u->v的邊長) 儲存到use[u]中。最後把use[u]中的邊按菊花圖的方法做一次貪心,就可以得到能夠構成的路徑條數的最大值:

for(int l=0,r=use[u].size()-1;r>=0;r--)

fans[u]+=mat; //儲存答案

貪心的想,在這裡一定要盡可能多的構成路徑,但是在這個條件下將盡可能長的乙個沒必要匹配的路徑留下來繼續向u的祖先連線;很明顯這也是存在單調性的——如果選擇一條長度為x的路徑「留下來」可以得到最大構成的路徑數,那麼長度小於x的路徑就一定也可以得到最大路徑數。

while(l+1>1;

if(check(u,mid,use[u].size(),num)==mat) l=mid;

else r=mid;

}dp[u]=use[u][l];

這樣就可以檢驗了,即看能夠得到的路徑條數是否能夠滿足要求。

(不知道大家看懂沒啊……有什麼問題的話還是直接在文末的作者郵箱裡面問吧qwq)

/*lucky_glass*/

#includeusing namespace std;

typedef long long ll;

const int n=50000;

struct edge

edge(int _to,int _nxt,ll _dis):to(_to),nxt(_nxt),dis(_dis){}

}edg[n*2+5];

int adj[n+5],edgtot;

void addedge(int u,int v,ll dis)

int n,m;

vector< int > use[n+5];

int dp[n+5],fans[n+5];

int check(int u,int tag,int siz,ll num)

return res;

}void dfs(int u,int pre,ll num)

sort(use[u].begin(),use[u].end());

int mat=0;

for(int l=0,r=use[u].size()-1;r>=0;r--)

fans[u]+=mat;

if(mat*2==use[u].size()) return;

int l=0,r=use[u].size();

while(l+1>1;

if(check(u,mid,use[u].size(),num)==mat) l=mid;

else r=mid;

}dp[u]=use[u][l];

}bool check(ll num)

int main()

if(check(r)) printf("%lld\n",r);

else printf("%lld\n",l);

return 0;

}

\(\mathcal\)

\(\mathcal\ 盡量在平時回答一下問題qwq\)

競賽題解 NOIP2018 旅行

坑還得一層一層的填 填到day2t1了洛谷 p5022 以下copy自洛谷,有刪減 修改 小 y 是乙個愛好旅行的 oier。她來到 x 國,打算將各個城市都玩一遍。小y了解到,x國的 n 個城市之間有 m 條雙向道路。每條雙向道路連線兩個城市。不存在兩條連線同一對城市的道路,也不存在一條連線乙個城...

NOIP2018 賽道修建

noip2018 賽道修建 樹形結構不帶樹上演算法走典型。用 dfs 即可,考慮的方向不能脫離樹狀結構。即考慮一棵子樹中分出的路線一定是獨立的,而那些沒用的邊可以傳上去作為備選答案。再考慮乙個貪心,我們每次上傳最大的即可。includeusing namespace std namespace ae...

NOIP2018 賽道修建 考場

題意 在一棵樹上選出m條路徑,這些路徑不能共用任意一條邊 問這些路徑中最小的一條路最大是多少這道題的部分分十分有意思,搞了一搞 第一種情況是m 1,即只選出一條最長的路徑 顯然是計算樹的直徑 int fa n ans 0 int dfs1 int u ans max ans,sum1 sum2 re...