noip 模擬賽 Po姐姐與他的妹子A

2021-08-21 17:39:14 字數 2674 閱讀 1701

a(a.cpp)

time limit:1s memory limit:128mb

【題目背景】

po姐姐很愛他的妹子,可是po姐姐並沒有妹子。於是po姐姐決定去找妹子。

【題目描述】

a國有n個城鎮,由n-1條道路連線,構成了乙個樹形結構。每條道路的長度都是一樣的。

po姐姐最近得到了乙個資訊:在a國的某些城鎮,可能出現質量上乘的妹子。

為了捕獲這些妹子,po姐姐製作了m個傳送器,準備將這些傳送器安置在一些城鎮中。一旦某個城鎮出現了妹子,po姐姐可以立刻傳送到某個傳送器所在的城鎮,然後沿道路移動到妹子所在的城鎮。po姐姐並不願意走太多的路,因此他會選擇離妹子最近的乙個傳送器傳送,然後走最短路到達妹子所在的城鎮。

po姐姐想要通過合理安排傳送器的位置,使得所有妹子可能出現的城鎮離最近傳送器的距離的最大值最小。

由於po姐姐懶癌發作,請你幫他寫乙個程式來解決這個問題。po姐姐懶得寫spj,你只需要輸出最大距離的最小值就行了。

【資料輸入】

第一行是兩個正整數n,m,表示a國城鎮的數量和傳送器的數量

接下來n個整數,每個整數都是1或0,如果第i個整數是1代表第i個城鎮可能出現質量上乘的妹子

接下來n-1行,每行兩個正整數x,y,表示x與y之間有一條雙向通行的道路

【資料輸出】

輸出一行乙個正整數,代表所有妹子可能出現的城鎮離最近傳送器的最大距離的最小值

【樣例輸入】

7 21 0 1 1 0 1 1

1 32 3

3 44 5

5 65 7

【樣例輸出】

1【樣例解釋】

如圖所示,在城鎮3和城鎮5上放置傳送器,這樣城鎮1、4、6、7離最近傳送器的距離為1,城鎮3離最近傳送器的距離為0,故最大值為1。

【資料範圍】

對於10%的資料,1<=m<=n<=10

對於40%的資料,1<=m<=n<=1000

對於100%的資料,1<=m<=n<=3*10^5

這題有難度啊

首先二分答案是很好想的,但是很久以前就看過一句話:「二分答案的考點永遠是在檢驗上。」

所以...怎麼檢驗呢?

在檢驗時,原題可以轉化為「已知每個點最大覆蓋的距離,求至少幾個點能覆蓋所有特殊點?」

那麼我們就可以用乙個樹形dp+貪心的思想來檢驗。

設我們要檢驗的答案為x:

貪心:只有當乙個節點離子樹內最遠的無人覆蓋的特殊點距離恰好為x時,我們才在這個節點上放置乙個傳送器(當然,根節點除外)。

在dp時,我們先搜尋後回溯更新:

設sta[i]表示i節點的狀態(只有1,2兩個值,1代表這個點的子樹中有特殊點未被覆蓋,離這個節點的距離為f[i],2代表這個點的子樹中有傳送器,傳送器還能覆蓋的最大範圍為f[i])(也就是說,由這個點狀態的不同,f陣列的含義不同!這點請千萬注意,我一開始就是不知道f陣列的含義才沒看懂題解...)

那麼對於每個點,我們列舉他的所有子節點,在回溯時判斷:

if(sta[to]==1)//表示這個點子樹中有節點還未被覆蓋但需覆蓋 

else if(sta[to]==2)//表示這個點子樹中沒有節點需要被覆蓋而且可以向上覆蓋

等判斷完,調整這個節點的狀態即可:

if(temp1>temp2)//能覆蓋別人的點覆蓋不到需要被覆蓋的點 

else

}else

貼整體**:

#include #include #include #include #include #include #include #include using namespace std;

struct edge

edge[600005];

int head[300005];

int cnt=1;

void init()

void add(int l,int r)

int n,m;

int tru[300005];

int f[300005];//記錄...

int sta[300005];//記錄每個節點的狀態,1代表..,2代表...

int tot=0;

void dfs(int x,int fx,int val)

else

for(int i=head[x];i!=-1;i=edge[i].next)

dfs(to,x,val);

if(sta[to]==1)//表示這個點子樹中有節點還未被覆蓋但需覆蓋

else if(sta[to]==2)//表示這個點子樹中沒有節點需要被覆蓋而且可以向上覆蓋

}if(temp1>temp2)//能覆蓋別人的點覆蓋不到需要被覆蓋的點

else

}else

}bool check(int x)

if(tot>m)

return 1;

}int divi()//二分答案

else

}return ans;

}int main()

for(int i=1;i

printf("%d\n",divi());

return 0;

}

2015 10 31的NOIP模擬賽

這是noip前的最後一周了。第一題是個組合數學的問題,規模不算太大。但第一反應就直接dp了,o n 2 的複雜度,始終想不到優化。本來看著1 3 4 6 10 15一串串數覺得多熟悉的,就是想不起來那是組合數。最後只有80分 第二題算是基本想到了吧,但是忽略了乙個問題 我的想法是每行0的個數要麼是當...

NOIP模擬賽 死宅與陷阱

題解 這是一道很簡單的dfs,只需要從s把圖跑一遍算出,每個點的到達概率。把他們存入乙個陣列,然後從大到小sort一遍,顯然概率越大的權值越應該加p,然後就把每個點的概率 權值就ok了。include define m 1000000009 using namespace std int head ...

NOIP模擬賽 盟主的憂慮

顯然任意所求路徑就只經過一條密道,然後呢,畫圖發現就是乙個個環,然後可以用並查集來維護屬於乙個環或者是直接賦值 includeusing namespace std long long read while ch 0 ch 9 return num struct ooedge 200005 stru...