NC13886

NC13886

題意

給你一顆n(偶數)結點的樹,將其分爲n/2對,求所有對數相連的路徑之和最小爲多少?

思路

DFS 數據結構
既然是圖論那就先畫圖吧在這裏插入圖片描述
左圖由於以2號結點爲根節點的子樹結點數(包括其自身)爲3(奇數),那麼顯然這棵樹上一定有個節點要從樹外找一個節點相連,那麼必須要經過2號結點與其父節點的這條路(2->1)。
右圖告訴我們如果能偶數配對的子樹則不需要相連。
葉子節點爲子樹的結點數一定爲1顯然一定會加上。
DFS求子樹的結點數,若結點數爲奇數則需要該節點與其父節點相連的這一條邊,若爲偶數則不需要。

注意:多組數據要每次清空vector數組,然後置於cnt數組不需要memset是因爲dfs裏面一開始都會賦過1,所以無影響。

#include<bits/stdc++.h>
#define fi first
#define se second
using namespace std;
typedef long long ll;
typedef pair<ll,ll>P;
const double eps = 1e-8;
const int NINF = 0xc0c0c0c0;
const int INF  = 0x3f3f3f3f;
const ll  mod  = 1e9 + 7;
const ll  maxn = 1e6 + 5;
const int N = 1e4 + 5;

ll res,n,cnt[N];
vector<P> G[N];

void dfs(ll u,ll fa,ll cost){
	cnt[u]=1;
	for(auto c:G[u]){
		ll x=c.fi,y=c.se;
		if(x==fa) continue;//若爲父節點當然不做啦
		dfs(x,u,y);//遞歸求子樹的節點數量
		cnt[u]+=cnt[x];
	}
	if(cnt[u]&1) res+=cost;
}

int main(){
	ios::sync_with_stdio(false);
	cin.tie(0);
	int T;cin>>T;
	while(T--){
		cin>>n;int t=n-1;res=0;
		for(int i=1;i<=n;i++) G[i].clear();
		while(t--){
			ll u,v,w;
			cin>>u>>v>>w;
			G[u].push_back(P(v,w));
			G[v].push_back(P(u,w));
		}
		dfs(1,-1,0);
		cout<<res<<'\n';
	}
	return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章