好厲害的一道題
loj較官方資料加強了好幾倍
顯然,乙個軍隊越靠根節點,能覆蓋到的節點越多
對答案一定是最優的,因為從這裡經過的路徑會更多
二分乙個答案mid
midmi
d,判斷能不能在mid
midmi
d的時間內覆蓋所有節點
上面已經有了乙個基本的貪心
乙個軍隊往根節點走是更優的
但是沒有軍隊的子樹呢?
那就貪心地只能從別的子樹排程乙個軍隊過來
顯然這裡需要排序了
我們存下根節點的所有子節點,就是根節點下面的一層節點
只要他們的葉節點都被覆蓋即可
再用乙個陣列f[i
]f[i]
f[i]
表示i
ii被覆蓋的最小時間
如果f [i
]<=m
id
f[i]<=mid
f[i]
<=m
id那麼也一定會有軍隊到達這個點
說的有點亂,看**通過陣列理解
#include
#define a 300010
using
namespace std;
typedef
long
long ll;
const ll inf =
1e15
;struct node e[a <<1]
;int head[a]
, num;
void
add(
int fr,
int to,
int w)
pairint> army[a]
, rtson[a]
; ll dis[a]
, f[a]
;int n, m, a, b, c, pos[a]
, which[a]
, cntson;
bool exist[a]
, vis[a]
, cov[a]
, use[a]
;//pos[i]:子樹i的軍隊中能跨過根節點的軍隊編號
//which[i]:i在根節點下的哪棵子樹中
//軍隊:a[i].first表示軍隊i初始所在位置,a[i].second表示軍隊i到根節點的距離
//根節點的子節點:rtson[i].first表示這個子節點的所在位置,rtson[i].second表示它與根的距離,也就是那一條邊的長度
//exist[i]:i這個點是否有軍隊
//f[i]:i被覆蓋所需的最短時間
//cntson:根的子節點有多少個
//cov[i]:i節點是否被覆蓋
void
dfs(
int fr,
int father)
}void
dfsroot
(int fr, ll mid)
else f[fr]
= inf;
cov[fr]=1
;bool flag =1;
//只有葉節點都被覆蓋或f[fr]<=mid這個點才叫被覆蓋
for(
int i = head[fr]
; i; i = e[i]
.next)
if(flag) cov[fr]=0
;if(f[fr]
<= mid) cov[fr]=1
;}intmain
(int argc,
char
const
*ar**)
for(
int i =
1; i <= m; i++
) army[i]
.first = dis[army[i]
.second]
;//排序貪心↓↓↓
sort
(army +
1, army + m +1)
;sort
(rtson +
1, rtson + cntson +1,
(pair<
int,
int> a, pair<
int,
int> b));
auto check =[&
](ll mid)
else use[pos[rtson[i]
.second]]=
1;}return
true;}
;while
(l <= r)
cout << ans << endl;
}
NOIP2012 簡要題解
day1 p1vigenere密碼 直接根據規律模擬即可 include include include include include using namespace std const int maxn 2000 char s maxn t maxn int calc char c int ma...
noip2012國王遊戲
game.cpp c pas 問題描述 恰逢 h 國國慶,國王邀請 n 位大臣來玩乙個有獎遊戲。首先,他讓每個大臣在左 右 手上面分別寫下乙個整數,國王自己也在左 右手上各寫乙個整數。然後,讓這 n位大臣排 成一排,國王站在隊伍的最前面。排好隊後,所有的大臣都會獲得國王獎賞的若干金幣,每 位大臣獲得...
NOIP2012 國王遊戲
題解 一開始看著題覺得是二分答案 最大值的最小值 後來發現不滿足單調性 再後來發現可以用貪心做 只需把大臣按照左手 右手公升序排序即可 證明 很顯然前面的大臣位置隨便調換對後面的大臣並沒有影響 那麼假設現在已經排了i 1個大臣,p a 1 a 2 a 3 a i 1 第i個大臣的錢w i p b i...