[CTSC2010]星際旅行 題解
阿新 • • 發佈:2021-07-02
[CTSC2010]星際旅行 題解
首先可以發現最優解一定是會遍歷完整棵樹的。
遍歷樹的過程恰好讓每一個\(h_i-=deg_i\)。
剩下的就變成匹配問題了,貪心地想一定是優先匹配外側點。
所以考慮從下往上匹配。
這樣就可以算出最終答案在根的答案。
然後考慮在\(v\)的答案。
可以理解成最後遍歷到\(v\)的時候直接停止,不走到根,這樣就相當於在\(v\)到\(root\)的鏈除了\(root\)外每一個\(h_i\)加上1.
考慮匹配多餘的\(1\),只需要從上往下掃一遍,多出來的\(1\)同層隨意匹配,同時向下的時候記錄\(fa\)的\(h_i\)。
/* { ###################### # Author # # Gary # # 2021 # ###################### */ #include<bits/stdc++.h> #define rb(a,b,c) for(int a=b;a<=c;++a) #define rl(a,b,c) for(int a=b;a>=c;--a) #define LL long long #define IT iterator #define PB push_back #define II(a,b) make_pair(a,b) #define FIR first #define SEC second #define FREO freopen("check.out","w",stdout) #define rep(a,b) for(int a=0;a<b;++a) #define SRAND mt19937 rng(chrono::steady_clock::now().time_since_epoch().count()) #define random(a) rng()%a #define ALL(a) a.begin(),a.end() #define POB pop_back #define ff fflush(stdout) #define fastio ios::sync_with_stdio(false) #define check_min(a,b) a=min(a,b) #define check_max(a,b) a=max(a,b) using namespace std; //inline int read(){ // int x=0; // char ch=getchar(); // while(ch<'0'||ch>'9'){ // ch=getchar(); // } // while(ch>='0'&&ch<='9'){ // x=(x<<1)+(x<<3)+(ch^48); // ch=getchar(); // } // return x; //} const int INF=0x3f3f3f3f; typedef pair<int,int> mp; /*} */ const int MAXN=5e4+233; int n,h[MAXN]; vector<int> g[MAXN]; int f[MAXN]; int dfs1(int now,int pre){ int Tmp=0; for(auto it:g[now]) if(it!=pre) { Tmp+=dfs1(it,now); int Z=min(h[now],h[it]); h[now]-=Z; h[it]-=Z; Tmp+=2*Z; } return Tmp; } void dfs2(int now,int pre,int pval,int tot,int depth=0){ if(now==1){ for(auto it:g[now]){ dfs2(it,now,h[now],tot,depth+1); } return ; } int Rst=h[now]+1; int sum=0; for(auto it:g[now]) if(it!=pre){ sum+=h[it]; } if(pval||sum){ Rst--; tot+=2; } f[now]=tot-depth; for(auto it:g[now]) if(it!=pre) { dfs2(it,now,Rst,tot,depth+1); } } int main(){ // freopen("1.in","r",stdin); // freopen("t.out","w",stdout); scanf("%d",&n); rb(i,1,n) scanf("%d",&h[i]); rb(i,1,n-1){ int u,v; scanf("%d%d",&u,&v); ++u,++v; g[u].PB(v); g[v].PB(u); } int tot=0; rb(i,1,n) tot+=g[i].size(),h[i]-=g[i].size(); // rb(i,1,n) cout<<h[i]<<' ';cout<<endl; tot+=dfs1(1,0); f[1]=tot; dfs2(1,0,0,tot); rb(i,1,n) printf("%d\n",f[i]); return 0; }