834. 树中距离之和

834. 树中距离之和

解法一:超时的暴力解法

#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
#include <map>
using namespace std;


class Solution {
public:
	bool confine = false;
	int start = 0;
	vector<int> sumOfDistancesInTree(int N, vector<vector<int>>& edges) 
	{
		vector<pair<vector<int>,vector<int>>> count(N);
		for (int i = 0; i < edges.size(); i++)
		{
			int first = edges[i][0];
			int second = edges[i][1];
			count[first].first.push_back(second);
			count[first].second.push_back(second);
			count[second].first.push_back(first);
			count[second].second.push_back(first);
		}
		vector<int>ans(N, 0);
		//vector<int>temp(N, -1);
		for (int i = 0; i < N; i++)
		{
			int count_edges = 0;
			int parent = i;
			for (int j = 0; j < N; j++)
			{

				if (i != j)
					sum(count_edges, count, j, parent,parent);
				ans[i] += count_edges;
 				count_edges = 0;
				confine = false;
			}
		}
		return ans;
	}
	
	void sum(int &count_edges, vector<pair<vector<int>, vector<int>>> count ,int end,int parent,int from)
	{
		for (int i = 0; i < count[parent].second.size(); i++)
		{
			int children = count[parent].second[i];
			count_edges++;

			if (children==end)
			{
				confine = 1;
				return;
			}
			if (count[children].second.size()>1&&children!=from)
			{
				sum(count_edges, count, end, children,parent);
			}
			if (confine)
				break;
			count_edges--;
		}
	}
};

int main()
{
	
	int N = 100;
	vector<vector<int>>edges = { {{74, 34},{67, 44},{81, 40},{1, 97},{44, 88},{95, 23},{77, 78},{67, 29},{98, 1},{89, 3},{60, 91},{30, 28},{64, 85},{47, 72},{64, 9},{26, 35},{24, 1},{43, 35},{62, 86},{92, 86},{59, 89},{31, 3},{31, 92},{1, 33},{54, 68},{57, 63},{2, 3},{36, 64},{6, 9},{3, 67},{99, 70},{9, 47},{45, 16},{94, 92},{22, 9},{56, 31},{89, 84},{40, 31},{37, 38},{57, 52},{75, 76},{1, 26},{65, 79},{5, 39},{96, 47},{55, 14},{83, 54},{6, 32},{11, 26},{8, 40},{32, 69},{32, 14},{78, 79},{34, 92},{31, 75},{39, 45},{3, 79},{71, 31},{82, 74},{51, 58},{27, 35},{60, 70},{31, 51},{53, 74},{64, 60},{84, 90},{39, 40},{28, 80},{0, 47},{31, 41},{1, 25},{56, 48},{93, 10},{1, 17},{37, 7},{47, 15},{49, 41},{5, 18},{4, 92},{25, 64},{84, 95},{10, 95},{63, 66},{46, 87},{92, 50},{66, 3},{64, 75},{61, 98},{78, 12},{54, 71},{7, 65},{87, 39},{73, 96},{61, 20},{64, 19},{21, 69},{30, 6},{42, 72},{13, 67}} };

		
	
	Solution s;
	s.sumOfDistancesInTree(N, edges);
	return 0;
}

超时的暴力解法2:思路都是差不多,解法二提高了代码的可读性;核心思想从parent开始遍历整个树

#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
#include <map>
#include <numeric>
using namespace std;


class Solution {
public:
	bool confine = false;
	int start = 0;
	vector<int> sumOfDistancesInTree(int N, vector<vector<int>>& edges) 
	{
		vector<pair<vector<int>,vector<int>>> count(N);
		for (int i = 0; i < edges.size(); i++)
		{
			int first = edges[i][0];
			int second = edges[i][1];
			count[first].first.push_back(second);
			count[first].second.push_back(second);
			count[second].first.push_back(first);
			count[second].second.push_back(first);
		}
		vector<int>ans(N, 0);
		for (int i = 0; i < N; i++)
		{
			vector<int>temp(N, -1);
			int count_edges = 0;
			int parent = i;
			temp[parent] = 0;
			sum(count_edges, count, temp, parent, parent);
			ans[parent] = accumulate(temp.begin(), temp.end(), 0);
			confine = 0;
		}
		return ans;
	}
	
	void sum(int &count_edges, vector<pair<vector<int>, vector<int>>> count , vector<int>&temp,int parent,int from)
	{
		for (int i = 0; i < count[parent].second.size(); i++)
		{
			int children = count[parent].second[i];
			count_edges++;
			if (temp[children]==-1)
			{
				temp[children] = count_edges;
			}
			if (find(temp.begin(),temp.end(),-1)==temp.end())
			{
				confine = 1;
				return;
			}
			if (count[children].second.size()>1&&children!=from)
			{
				sum(count_edges, count,temp, children,parent);
			}
			if (confine)
				break;
			count_edges--;
		}
	}
};

int main()
{
	
	/*int N = 100;
	vector<vector<int>>edges = { {{74, 34},{67, 44},{81, 40},{1, 97},{44, 88},{95, 23},{77, 78},{67, 29},{98, 1},{89, 3},{60, 91},{30, 28},{64, 85},{47, 72},{64, 9},{26, 35},{24, 1},{43, 35},{62, 86},{92, 86},{59, 89},{31, 3},{31, 92},{1, 33},{54, 68},{57, 63},{2, 3},{36, 64},{6, 9},{3, 67},{99, 70},{9, 47},{45, 16},{94, 92},{22, 9},{56, 31},{89, 84},{40, 31},{37, 38},{57, 52},{75, 76},{1, 26},{65, 79},{5, 39},{96, 47},{55, 14},{83, 54},{6, 32},{11, 26},{8, 40},{32, 69},{32, 14},{78, 79},{34, 92},{31, 75},{39, 45},{3, 79},{71, 31},{82, 74},{51, 58},{27, 35},{60, 70},{31, 51},{53, 74},{64, 60},{84, 90},{39, 40},{28, 80},{0, 47},{31, 41},{1, 25},{56, 48},{93, 10},{1, 17},{37, 7},{47, 15},{49, 41},{5, 18},{4, 92},{25, 64},{84, 95},{10, 95},{63, 66},{46, 87},{92, 50},{66, 3},{64, 75},{61, 98},{78, 12},{54, 71},{7, 65},{87, 39},{73, 96},{61, 20},{64, 19},{21, 69},{30, 6},{42, 72},{13, 67}} };
*/
		
	int N = 6;
	vector<vector<int>> edges = {{0, 1}, {0, 2}, {2, 3}, {2, 4}, {2, 5}};
	Solution s;
	s.sumOfDistancesInTree(N, edges);
	return 0;
}

[leetcode]834. Sum of Distances in Tree

class Solution {
public:
	//相当于图来存来处理
	vector<vector<int>> tree;
	vector<int> res;
	vector<int> subc;
	int n;
	vector<int> sumOfDistancesInTree(int N, vector<vector<int>>& edges) {
		//tree.rvec(N,vector<int>(N));
	   //init
		n = N;
		tree.resize(N);            //初始化的函数
		res.assign(N, 0);
		subc.assign(N, 0);
		//build tree
		for (auto e : edges) {               //遍历的技巧
			tree[e[0]].push_back(e[1]);
			tree[e[1]].push_back(e[0]);
		}
		set<int> visited1;
		set<int> visited2;
		DFS_POST(0, visited1);         //初始root任何值都行
		DFS_PRE(0, visited2);
		return res;

	}
	void DFS_POST(int root, set<int> &visited)
	{
		//传引用保存修改值
		visited.insert(root);
		for (auto i : tree[root]) 
		{
			if (visited.find(i) == visited.end())
			{
				DFS_POST(i, visited);
				subc[root] += subc[i];
				res[root] += res[i] + subc[i];
			}
		}
		subc[root]++;  //加上自身节点
	}
	void DFS_PRE(int root, set<int> &visited)
	{
		visited.insert(root);
		for (auto i : tree[root]) {
			if (visited.find(i) == visited.end()) {
				res[i] = res[root] - subc[i] + n - subc[i];         //算法核心
				DFS_PRE(i, visited);
			}
		}
	}

};

DFS_PRE,DFS_POST两个算法,

其中DFS_POST 计算每个根节点都有多少个子根(包含其自身)(从上到下遍历)

DFS_PRE 才是用来计算每个节点到其他节点的距离,其中关键的函数关系式是下面这句话

res[i] = res[root] - subc[i] + n - subc[i];

选中的节点到其他节点距离之和是选中节点的根节点到其他节点距离之和减去选中节点的子节点数加上节点个数减去改节点的子节点数(如果是叶节点就是排除自身;如果是根节点,减去所有根节点和其所有的子节点);

猜你喜欢

转载自blog.csdn.net/kongqingxin12/article/details/83118306