題意:
給出一顆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 4view codeusing
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 }
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 國的首都爆發了一種危害性極高的傳染病。當局為了控制疫情,不讓疫情擴散到邊境 城市 葉子節點所表示的城市 決定動用軍隊在一些城市建立檢查點,使得從首都到邊境 城市的每一條路徑上都至少有...