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;
}