noip2012 疫情控制

2022-06-04 06:15:11 字數 1921 閱讀 9660

題意:

給出一顆n個節點有邊權的樹 和m個軍隊所在的位置 軍隊從某節點移動到相鄰節點要花費邊長度的時間 求最少要多少時間使得根節點(編號為1)到每個葉子的路徑上最少有一支軍隊(根節點不能有軍隊)

題解:

我們可以二分答案 那麼問題就轉換為 在t的時間內軍隊能否控所有點

顯然一支軍隊在到根節點之前 如果能繼續向上走 那麼這支軍隊能控制的點就會更多

維護bo[i]表示 從該點到所有該點子樹的葉子節點路徑上是否都有軍隊

對於每個不能走到根節點的軍隊 就讓他盡量向上走 直到不能走為止 將該點的bo值賦為1 然後可以用拓撲算出bo陣列

這樣 根節點的所有兒子中bo為1的點就不用管 而剩下的點就需要派能走到根節點的軍隊到這些點控制

於是問題轉換為 有n0個點需要被控制 且控制該點需要li的時間 還有m0支軍隊 每支軍隊有ti的時間 求這m0支軍隊是否能控制這n0個點

這原本這樣將l和t分別排序 貪心用兩個指標乙個個掃就行了

但是要注意的是如果軍隊j就是從i點走到首都的 那麼該軍隊不論有多少剩餘時間都能控制該點(去年noip考試的時候好像就是沒想到這點)

這個問題我們只要做乙個小轉換就行了 如果i點有軍隊從該點到達首都 那麼用minarm[i]記下這些軍隊中剩餘時間最少的是誰 當指標掃到i時先判斷minarm[i]是否被用過了 如果沒有 那麼用minarm[i]來控制i 否則再在j指標上找軍隊

證明:如果minarm[i]沒被使用 那麼t[j]>=t[minarm[i]] 所以在i點如果用minarm[i]則能省下乙個剩餘時間更多的軍隊 對於之後可能用到minarm[i]的點完全可以用j點代替

**:

1 #include 2 #include 3 #include 4

using

std::sort;

5const

int n=50001;6

struct

inli

10 }line[n*2

];11

struct

info

15}ar[n],ci[n];

16 inline bool cmp(info a,info b)

17int

n,m,na,nc,fat[n],ti[n],gra[n],dis[n],arm[n],nl,son[n],mint[n],add,boo[n];

18int max(int x,int y)

19void dfs(int

t)29

if (t!=1 &&line[son[t]].next)34}

35void maketi(int

t)40

void makear(int

t)50}51

void

makeci()

57bool

work()

68return1;

69}70bool check(int

t)78

intgetans()

85return

r;86}87

void makefat(int

t)97}98

intmain()

108 makefat(1

);109 scanf("

%d",&m);

110if (m

114for (int i=1;i<=m;i++) scanf("

%d",&arm[i]);

115 sort(arm+1,arm+m+1

);116 printf("%d"

,getans());

117fclose(stdin);

118fclose(stdout);

119 }

view code

NOIP2012 疫情控制

詳細的注釋已經寫到了 裡面。以後這種碼量多的最好都寫成函式再呼叫,確定好每個函式的作用。然後變數名最好也是有實際意義的qwq include include include include include define maxn 500010 using namespace std int n,m,...

NOIP 2012 疫情控制

題目鏈結 演算法 細心觀察發現 此題的答案具有單調性,也就是說,如果p小時能控制疫情,那麼q小時也能控制疫情 q p 因此我們可以二分答案,這是此題的突破口 問題就轉化為了檢驗 mid小時是否可以控制住疫情 我們發現,既然要求所有葉子節點得到管轄,那麼,軍隊所在的節點深度越淺,所能管轄的節點數就越多...

NOIP 2012 疫情控制

h 國有 n 個城市,這 n 個城市用 n 1 條雙向道路相互連通構成一棵樹,1 號城市是首都,也是樹中的根節點。h 國的首都爆發了一種危害性極高的傳染病。當局為了控制疫情,不讓疫情擴散到邊境 城市 葉子節點所表示的城市 決定動用軍隊在一些城市建立檢查點,使得從首都到邊境 城市的每一條路徑上都至少有...