解法一:超时的暴力解法
#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];