51Nod-1405-树的距离之和

来源:互联网 发布:淘宝收入来源 编辑:程序博客网 时间:2024/06/03 15:56

ACM模版

描述

描述

题解

根据题意,这是一颗树,所以每两点之间的路径一定是唯一的。这里让求所有点到第i个结点的距离和,其实也就是其他所有结点到第i个结点的距离和。

通过观察发现,只要我们找到了一个点对应的结果,那么其他所有的点都可以通过这个结果扩展出来,利用边的关系。比如说,我们知道了第一个结点对应的结果,并且知道第一个和第二个存在连边,那么一定可以通过第一个的结果求得第二个结果……以此类推。

所以,我们先dfs,求第一个结点的对应结果(当做根,也可以是别的结点当做根),并且存储该树每个枝杈上的后代数目(包括其本身),这个数据对求其他结果至关重要,接着我们再通过第二个dfs扩展出其他结果即可。

另外附一份树归的解法(Two)……

代码

One:

#include <iostream>#include <vector>#include <cstdio>using namespace std;typedef long long ll;const int MAXN = 1e5 + 5;int n;ll res[MAXN];int des[MAXN];vector<int> node[MAXN];void dfs(int lastPos, int pos, int power){    for (int i = 0; i < node[pos].size(); i++)    {        if (node[pos][i] != lastPos)        {            res[1] += (node[node[pos][i]].size() - 1) * power;            dfs(pos, node[pos][i], power + 1);            des[pos] += des[node[pos][i]];        }    }    return ;}void dfs_(int lastPos, int pos){    for (int i = 0; i < node[pos].size(); i++)    {        if (node[pos][i] != lastPos)        {            res[node[pos][i]] = res[pos] - des[node[pos][i]] + n - des[node[pos][i]];            dfs_(pos, node[pos][i]);        }    }    return ;}int main(int argc, const char * argv[]){//    freopen("/Users/zyj/Desktop/input.txt", "r", stdin);    cin >> n;    int x, y;    for (int i = 1; i < n; i++)    {        scanf("%d %d", &x, &y);        node[x].push_back(y);        node[y].push_back(x);    }    res[1] = node[1].size();    for (int i = 1; i <= n; i++)    {        des[i] = 1;    }    dfs(0, 1, 2);    dfs_(0, 1);    for (int i = 1; i <= n; i++)    {        printf("%lld\n", res[i]);    }    return 0;}

Two:

#include <iostream>#include <cstdio>#include <cstring>#define MAXN 100009using namespace std;typedef struct{    int a;    int next;} point;point p[2 * MAXN];typedef struct{    long long n;    long long w;} r;r R;int dis[MAXN];long long dp[2 * MAXN][2];void DFS(int a, int last){    int i;    long long ans = 0, count = 0;    for (i = dis[a]; i != 0; i = p[i].next)    {        if (p[i].a != last)        {            if (dp[i][0] != -1)            {                ans += dp[i][0] + dp[i][1];                count += dp[i][1];            }            else            {                DFS(p[i].a, a);                dp[i][0] = R.w;                dp[i][1] = R.n;                ans += R.w + R.n;                count += R.n;            }        }    }    R.n = count + 1;    R.w = ans;    return ;}int main (){    int N, k = 1, a, b;    memset(dp, -1, sizeof(dp));    scanf("%d", &N);    for (int i = 1; i < N; i++)    {        scanf("%d%d", &a, &b);        p[k].a = a;        p[k].next = dis[b];        dis[b] = k++;        p[k].a = b;        p[k].next = dis[a];        dis[a] = k++;    }    for (int i = 1, sz = N + 1; i < sz; i++)    {        DFS(i, 0);        printf("%lld\n", R.w);    }    return 0;}
0 0
原创粉丝点击