noip2012 疫情控制

2022-06-02 10:09:12 字數 2919 閱讀 1350

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

h國的首都爆發了一種危害性極高的傳染病。當局為了控制疫情,不讓疫情擴散到邊境城市(葉子節點所表示的城市),決定動用軍隊在一些城市建立檢查點,使得從首都到邊境城市的每一條路徑上都至少有乙個檢查點,邊境城市也可以建立檢查點。但特別要注意的是,首都是不能建立檢查點的。 

現在,在h國的一些城市中已經駐紮有軍隊,且乙個城市可以駐紮多個軍隊。一支軍隊可以在有道路連線的城市間移動,並在除首都以外的任意乙個城市建立檢查點,且只能在乙個城市建立檢查點。一支軍隊經過一條道路從乙個城市移動到另乙個城市所需要的時間等於道路的長度(單位:小時)。 

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

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

接下來的n-1行,每行3個整數,u、v、w,每兩個整數之間用乙個空格隔開,表示從城市u到城市v有一條長為w的道路。資料保證輸入的是一棵樹,且根節點編號為1。 

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

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

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

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

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

對於40%的資料,2 ≤n≤50,0應該算是一道厲害的二分+貪心吧 ;

如果軍隊數小於根結點的兒子數顯然無解- =,不讓必然有解。

很容易想到軍隊玩往樹上爬,爬到頂了,可以爬到沒被控制的1的葉子節點,直到把所有點控制。

然後想到二分時間讓它們爬。

然後我就不會了。。想不到科學的檢驗能否控制方法0_0,然後找g-word講解了。。。

如何檢測能否控制 :

在二分的限制時間 t 裡,把軍隊分成兩類 :

a 不能到達1的,也就是沒機會爬到1的其他葉子節點 ;

b 能到達1的,有機會爬到1的其他葉子節點;

對於通過a類可以求出當前a類未能控制的節點,及其由根結點1到其的路程;

通過b類可求出b類所有點到1所剩的時間。

顯然所剩時間多的,要去控制路程長的- =,可以排個序(貪心),搞個裸匹配。

但這樣會出現自己跑會自己原來節點的情況- = 

搞個細節處理之 : 

從大到小排序(從到大小進行匹配)

如果當前的軍隊要控制的節點是後面某個節點走出來的節點 ,

顯然,當前軍隊所剩時間最多,他要控制的路徑如果可以用後面節點控制,顯然會更省時,也更科學;

所以當要控制節點p,如果從它走出來的軍隊還未使用,就用其中所剩時間最小的控制之- = 

搞幾個陣列搞之即可。。。 

ps.這題還是開long long吧。。

**如下:

1 #include2 #include3 #include4 #include

5 #include6 #include7

#define inf 999999999999

8#define ll long long

9#define max(x,y) if(x10

#define n 100003

11using

namespace

std ;

12struct

p15 p(const ll x,const

ll y) : p(x),t(y){}

16}army[n],edge[n];

17bool cmp(const p &x,const p &y)

20ll n,m,t;

21 ll next[n*2],last[n*2],to[n*2

];22 ll w[n*2

];23 ll p[n],from

[n],root[n];

24ll dis[n],left[n];

25bool

use[n];

26 queueq;

27 inline void

addedge(ll a,ll b,ll c)

31void

fail()38}

39ll pushup(ll now,ll f)

44 use[now]=1;45

for(ll i=last[now];i;i=next[i])

46if(to[i]!=f)

50if(left[now]>=0) use[now]=1;51

return

left[now];52}

53bool

check(ll lim)

83if(!use[from

[edge[lb].p]])

88if(army[la].treturn

false

;89 use[la]=1

;90 ++la ;

91 ++lb ; 92}

93return

true

; 94}95

void

prework()

109}

110}

111int

main()

120 scanf("

%i64d

",&m);

121fail();

122for(ll i=1;i<=m;i++) scanf("

%i64d

",&p[i]);

123 ll ans,l=0,r=1000000000000ll;

124prework();

125while(l<=r) else l=mid+1

;131

}132 printf("

%i64d

",ans);

133 }

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