NOIP 2012 疫情控制

2022-05-11 12:28:57 字數 3835 閱讀 4229

h 國有 n 個城市,這 n 個城市用 n-1 條雙向道路相互連通構成一棵樹,1 號城市是首都,

也是樹中的根節點。

h 國的首都爆發了一種危害性極高的傳染病。當局為了控制疫情,不讓疫情擴散到邊境

城市(葉子節點所表示的城市),決定動用軍隊在一些城市建立檢查點,使得從首都到邊境

城市的每一條路徑上都至少有乙個檢查點,邊境城市也可以建立檢查點。但特別要注意的是,

首都是不能建立檢查點的。

現在,在 h 國的一些城市中已經駐紮有軍隊,且乙個城市可以駐紮多個軍隊。一支軍隊可以在有道路連線的城市間移動,並在除首都以外的任意乙個城市建立檢查點,且只能在

乙個城市建立檢查點。一支軍隊經過一條道路從乙個城市移動到另乙個城市所需要的時間等

於道路的長度(單位:小時)。

請問最少需要多少個小時才能控制疫情。注意:不同的軍隊可以同時移動。

輸入格式:

第一行乙個整數 n,表示城市個數。

接下來的 n-1 行,每行 3 個整數,u、v、w,每兩個整數之間用乙個空格隔開,表示從

城市 u 到城市 v 有一條長為 w 的道路。資料保證輸入的是一棵樹,且根節點編號為 1。

接下來一行乙個整數 m,表示軍隊個數。

接下來一行 m 個整數,每兩個整數之間用乙個空格隔開,分別表示這 m 個軍隊所駐紮

的城市的編號。

輸出格式:

共一行,包含乙個整數,表示控制疫情所需要的最少時間。如果無法控制疫情則輸出-1。

輸入樣例#1:

4 

1 2 1

1 3 2

3 4 3

2 2 2

輸出樣例#1:

3

【輸入輸出樣例說明】

第一支軍隊在 2 號點設立檢查點,第二支軍隊從 2 號點移動到 3 號點設立檢查點,所需

時間為 3 個小時。

【資料範圍】

保證軍隊不會駐紮在首都。

對於 20%的資料,2≤ n≤ 10;

對於 40%的資料,2 ≤n≤50,0對於 60%的資料,2 ≤ n≤1000,0對於 80%的資料,2 ≤ n≤10,000;

對於 100%的資料,2≤m≤n≤50,000,0noip 2012 提高組 第二天 第三題

題解:

貪心,首先乙個點要盡可能往上跳,不會往下跳

二分答案t,將每個軍隊在t時間內盡可能往上跳,用倍增實現

最麻煩的是乙個子樹內的點要跳到另乙個子樹

一開始貪心,把能跳到1點的剩餘距離存下,再dfs找出需要軍隊的子樹,排序後填入

但這樣錯了,有70分

因為會有到1還有距離的點x,放下自己的子樹去控制別的子樹,或者這棵子樹必須由x控制

參考了yzh大佬%%%%%orz的部落格後知道了

假設軍隊已經盡可能往上到了x,key[x]表示x能否控制相應子樹,如果key[x]&&x!=1 則說明這個點能控制子樹,且不參與到軍隊在不同子樹間的轉移,到達1點的軍隊要參與轉移,所以不計

mins[x]為經過x子樹的剩餘距離最小值的軍隊編號,這個軍隊守好自己的子樹就行了

d[x]表示x子樹是否被控制

我們把能到1,且不含於mins的軍隊按剩餘距離排序為q陣列

再把未被控制(d[x]==0)的子樹按與1的距離排序為c,然後匹配

提供鏈結orz:

1 #include2 #include3 #include4 #include5

using

namespace

std;

6struct

node

7edge[100001

];11

struct

que12

q[100001],c[100001

];16

int num,head[100001],n,m,fa[100001][21],pos[100001],dep[100001],mins[100001

];17

long

long s[100001][21],ans,bel[100001

];18

int b[100001],tt,top,du[100001

],ddt;

19bool us[100001],d[100001],key[100001

];20

void add(int u,int v,long

long

d)21

28bool

cmp(que a,que b)

2932

bool

exam()

33 42

while (us[q[j].id]&&j<=tt) j++;

43if (j>tt) return0;

44if (q[j].sreturn0;

45 us[q[j].id]=1;46

}47return1;

48}49bool check(long

long

w)50 65}

66if (du[x]==1) cnt++;

67if (x==1)68

74else

if (key[x]) d[bel[x]]=1;75

}76if (cnt==ddt) return1;

77for (i=head[1];i;i=edge[i].next)

7886}87

if (!top) return1;

88return

exam();89}

90void prework(int x,int

last)

91 102

}103

}104

void belon(int x,int pa,int

be)105

114}

115}

116void dfs(int x,int

pa)117

124for (i=head[x];i;i=edge[i].next)

125133

}134

}135

intmain()

136

147for (i=1;i<=n;i++)

148if (du[i]==1) ddt++;

149 cin>>m;

150for (i=1;i<=m;i++)

151 scanf("

%d",&pos[i]);

152 dfs(1,0

);153

for (i=head[1];i;i=edge[i].next)

154 belon(edge[i].to,1

,edge[i].to);

155 key[0]=1

;156 prework(1,0

);157 l=0;r=sum;

158while (l<=r)

159165

if(ans)

166 cout<167else cout<<-1

;168 }

NOIP2012 疫情控制

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

NOIP 2012 疫情控制

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

noip2012 疫情控制

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