2020ccpc秦皇島K題


就是給你一棵樹,從1號根開始放無數個機器人,要機器人覆蓋所有邊的最小路徑和;

 

可以樹形DP但是沒必要,假設只有一個機器人的時候,答案就是  邊數*2 - 根離最遠的葉子的距離,兩個機器人的時候就相當於把走過兩次的邊改成一次,犧牲一些邊獲取一些邊,算貢獻的方法;

具體可以看代碼

 

#include<iostream>
#include<cstring>
#include<algorithm>
#include<vector>
using namespace std;
typedef long long ll;
const int maxn = 1e6+11;
vector<int>G[maxn];
void add(int x,int y){
	G[x].push_back(y);
}
ll ans =0 ;
ll dp[maxn];
ll dep[maxn];




int dfs(int x,int fa,int d){
	dep[x] = d;                  
	for(int i=0;i<G[x].size();i++){
		int p = G[x][i];
		if(p == fa) continue;
		dfs(p,x,d+1);
		dp[x] = max(dp[x],dp[p]+1);
	}
	return 0;
}
bool bml(int a,int b){
	return dp[a] > dp[b];
}


int dfs2(int x,int fa,int flag){
	//flag==1不能計算
	
	sort(G[x].begin(),G[x].end(),bml);
	if(flag == 0){
		ans += min(dep[x] - dp[x] - 2,0LL);
	}
	
	int f = 0;
	for(int i=0;i<G[x].size();i++){
		int p = G[x][i];
		if(p == fa) continue;
		f++;
		if(f == 1){
			dfs2(p,x,1);
		}
		else{
			dfs2(p,x,0);
		}
	} 
	
	return 0;
}




int main(){
	
	
	int t;
	int aa = 0;
	scanf("%d",&t);
	while(t--){
		int n;
		scanf("%d",&n);
		for(int i=0;i<=n;i++){
			dep[i] = 0;
			dp[i] = 0;	
			G[i].clear();
		}
		
		for(int i=2;i<=n;i++){
			int x;
			scanf("%d",&x);
			add(x,i);
			add(i,x);
		}
		dfs(1,0,0);
		ans = (n-1)*2 - dp[1];
		
		dfs2(1,0,1);
		
		printf("Case #%d: %lld\n",++aa,ans);
		
		
	}
	return 0;
} 

  


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM