Jumping Monkey(CCPC网络赛重赛)
Jumping Monkey(CCPC網(wǎng)絡(luò)賽重賽)
題意:
n個(gè)點(diǎn)的樹(shù),每個(gè)點(diǎn)有一個(gè)不同的值aia_iai?.現(xiàn)在一個(gè)猴子在樹(shù)上,這個(gè)猴子從點(diǎn)u跳到點(diǎn)v當(dāng)且僅當(dāng)ava_vav?是u到v最短路徑上的最大值。如果沒(méi)有點(diǎn)能跳將停止。
對(duì)于k∈[1,n],計(jì)算猴子在點(diǎn)k開(kāi)始最多能跳的點(diǎn)數(shù)量
題解:
每次跳躍點(diǎn)u,u要是路徑上的最大值。如果點(diǎn)權(quán)最大的那個(gè)節(jié)點(diǎn)(設(shè)為u),顯然無(wú)論從哪里開(kāi)始跳,都可以直接到達(dá)u,且無(wú)法越過(guò)u到達(dá)其他點(diǎn),到達(dá)u后也不能再跳向其他結(jié)點(diǎn)。也就是說(shuō)u是最優(yōu)方案中最后一個(gè)到達(dá)的點(diǎn)。那u的位置已經(jīng)被固定了,將u從樹(shù)上去掉,對(duì)剩下的每個(gè)連通塊都遞歸上述過(guò)程,這樣確定的新樹(shù),深度就是其答案。
但是上述的遞歸不好實(shí)現(xiàn),我們逆向考慮這個(gè)過(guò)程:我們將點(diǎn)權(quán)按照從小到大枚舉,當(dāng)前枚舉到點(diǎn)u,將u作為所有與u相連的(必須是已經(jīng)枚舉過(guò)的,也就是點(diǎn)權(quán)比u小的)連通塊的跟。這樣得到的一顆新樹(shù),u是v的父親,說(shuō)明u的點(diǎn)權(quán)大于v,其原樹(shù)中u與v之間存在邊,那v就是到達(dá)它的所有父親點(diǎn),所以每個(gè)節(jié)點(diǎn)的深度就是答案
復(fù)雜度O(nlog n)
代碼:
#include <bits/stdc++.h> #include <unordered_map> #define debug(a, b) printf("%s = %d\n", a, b); using namespace std; typedef long long ll; typedef unsigned long long ull; typedef pair<int, int> PII; clock_t startTime, endTime; //Fe~Jozky const ll INF_ll= 1e18; const int INF_int= 0x3f3f3f3f; void read(){}; template <typename _Tp, typename... _Tps> void read(_Tp& x, _Tps&... Ar) {x= 0;char c= getchar();bool flag= 0;while (c < '0' || c > '9')flag|= (c == '-'), c= getchar();while (c >= '0' && c <= '9')x= (x << 3) + (x << 1) + (c ^ 48), c= getchar();if (flag)x= -x;read(Ar...); } template <typename T> inline void write(T x) {if (x < 0) {x= ~(x - 1);putchar('-');}if (x > 9)write(x / 10);putchar(x % 10 + '0'); } void rd_test() { #ifdef ONLINE_JUDGE #elsestartTime = clock ();freopen("data.in", "r", stdin); #endif } void Time_test() { #ifdef ONLINE_JUDGE #elseendTime= clock();printf("\nRun Time:%lfs\n", (double)(endTime - startTime) / CLOCKS_PER_SEC); #endif } const int maxn=2e5+9; PII val[maxn]; bool vis[maxn]; int fa[maxn]; vector<int>vec[maxn]; vector<int>g[maxn]; int dep[maxn]; int find(int x){if(fa[x]==x)return x;return fa[x]=find(fa[x]); } void dfs(int u){for(auto v:g[u]){dep[v]=dep[u]+1;dfs(v);} } int main() {//rd_test();int t;read(t);while(t--){int n;cin>>n;for(int i=1;i<=n;i++)vis[i]=0;for(int i=1;i<=n;i++)fa[i]=i;for(int i=1;i<n;i++){int u,v;read(u,v);vec[u].push_back(v);vec[v].push_back(u);}for(int i=1;i<=n;i++){read(val[i].first);val[i].second=i;}sort(val+1,val+1+n);for(int i=1;i<=n;i++){int u=val[i].second;vis[u]=1;for(auto v:vec[u]){if(vis[v]==0)continue;int fv=find(v);fa[fv]=u;g[u].push_back(fv);}}dep[val[n].second]=1;dfs(val[n].second);for(int i=1;i<=n;i++)cout<<dep[i]<<endl;for(int i=0;i<=n;i++){g[i].clear(); vec[i].clear();}}return 0;//Time_test(); }總結(jié)
以上是生活随笔為你收集整理的Jumping Monkey(CCPC网络赛重赛)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 发烧了可以泡脚吗
- 下一篇: Bigraph Extension