牛客練習賽40 C-小A與歐拉路(樹形dp | 兩次dfs 求樹的直徑)

C-小A與歐拉路

題意:求圖中最短的歐拉路。
題解:因爲是一棵樹,因此當從某一個節點遍歷其子樹的時候,如果還沒有遍歷完整個樹,一定還需要再回到這個節點再去遍歷其它子樹,因此除了從起點到終點之間的路,其它路都被走了兩次,而我們要求總的路程最短,那麼我們就讓從起點到終點的路最長即可,也就是樹的直徑。所以答案就是所有邊權的兩倍再減去樹的直徑。

代碼

  • 兩次dfs
#include<bits/stdc++.h>

#define DEBUG(x) std::cerr << #x << '=' << x << std::endl
#define P pair<int,LL>
typedef long long LL;
using namespace std;
const int N = 2E5+10;
LL d[N];
vector<P> E[N];
void dfs(int u,int fa)
{
	for(auto &it : E[u]) {
		int v = it.first;
		LL w = it.second;
		if(fa == v) continue;
		d[v] = d[u] + w;
		dfs(v,u);
	}
}

int main()
{
#ifndef ONLINE_JUDGE
    freopen("input.in","r",stdin);
#endif
	ios::sync_with_stdio(false);
	cin.tie(0);
	int n, u, v, w;
	LL sum = 0;
	cin >> n;
	for(int i = 0; i < n - 1; ++i) {
		cin >> u >> v >> w;
		E[u].push_back(P(v,w));
		E[v].push_back(P(u,w));
		sum += 2 * w;
	}
	dfs(1,0);
	int rt = 1;
	for(int i = 1; i <= n; ++i) {
		if(d[rt] < d[i]) rt = i;
		DEBUG(d[i]);
	}
	d[rt] = 0;
	dfs(rt,0);
	cout << sum - *max_element(d + 1,d + n + 1) << endl;
    return 0;
}

  • 樹形dp
#include<bits/stdc++.h>

#define DEBUG(x) std::cerr << #x << '=' << x << std::endl
#define P pair<int,int>
using namespace std;
const int N = 2E5+10;
typedef long long LL;
LL dp[N][2], maxL;
vector<P> E[N];

void dfs(int u,int fa)
{
	for(auto &it : E[u]) {
		int v = it.first;
		int w = it.second;
		if(fa == v) continue;
		dfs(v,u);
		if(dp[v][0] + w > dp[u][0]) { //如果以u爲根節點的最長鏈可以被它的兒子v更新
			dp[u][1] = dp[u][0]; //那麼此時以u爲根節點的次長鏈變爲dp[u][0];
			dp[u][0] = dp[v][0] + w; //最長鏈被更新
		}else if(dp[v][0] + w > dp[u][1]) { //如果不能更新最長鏈但是卻可以更新次長鏈
			dp[u][1] = dp[v][0] + w;
		}
	}	
	maxL = max(maxL,dp[u][1] + dp[u][0]);
}

int main()
{
#ifndef ONLINE_JUDGE
    freopen("input.in","r",stdin);
#endif
	ios::sync_with_stdio(false);
	cin.tie(0);
	int n,u,v,w;
	LL sum = 0;
	cin >> n;
	for(int i = 0; i < n - 1; ++i) {
		cin >> u >> v >> w;
		E[u].push_back(P(v,w));
		E[v].push_back(P(u,w));
		sum += 2 * w;
	}
	dfs(1,0);
	cout << sum - maxL << endl;
    return 0;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章