国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學院 > 開發(fā)設計 > 正文

51nod 1405 樹的距離之和 【dfs--記憶dp??樹形dp??】

2019-11-06 08:20:59
字體:
供稿:網(wǎng)友

1405 樹的距離之和基準時間限制:1 秒 空間限制:131072 KB 分值: 40 難度:4級算法題給定一棵無根樹,假設它有n個節(jié)點,節(jié)點編號從1到n, 求任意兩點之間的距離(最短路徑)之和。Input
第一行包含一個正整數(shù)n (n <= 100000),表示節(jié)點個數(shù)。后面(n - 1)行,每行兩個整數(shù)表示樹的邊。Output
每行一個整數(shù),第i(i = 1,2,...n)行表示所有節(jié)點到第i個點的距離之和。Input示例
41 23 24 2Output示例
5355曹鵬 (題目提供者)

題解:

先定義四個概念--

lower_sum 表示此點的全部孩子到此點的距離之和。dian_sum為此點和孩子點的總個數(shù)。border_sum 為 非此點孩子的節(jié)點到此點的距離之和。

ans_sum 為此點到所有點之和。

然后第一編dfs求解lower_sum 和 dian_sum  

第二遍dfs求解 border_sum 和 ans_sum

代碼:

//每個邊的利用率為 n *  m ----   總和  --#include<stdio.h>#include<string.h>#include<vector>#include<iostream>#include<algorithm>using namespace std;#define LL long longvector<int> V[100100];struct node{    LL lower_sum,dian_sum,border_sum,ans_sum;/*    lower_sum 表示此點的全部孩子到此點的距離之和,    dian_sum為此點和孩子點的總個數(shù),    border_sum 為 非此點孩子的節(jié)點到此點的距離之和。 */}pp[100100];LL ans;int n;void dfs_one(int x,int f){    pp[x].dian_sum=1;    for (int i=0;i<V[x].size();i++)    {        int v=V[x][i];        if (v==f) continue;        dfs_one(v,x);        pp[x].lower_sum+=pp[v].dian_sum+pp[v].lower_sum;        pp[x].dian_sum+=pp[v].dian_sum;    } //   cout<<x<<' '<<pp[x].dian_sum<<' '<<pp[x].lower_sum<<' '<<pp[x].border_sum<<endl;}void dfs_two(int x,int f){    if (f!=-1)    {        pp[x].border_sum=pp[f].border_sum+pp[f].lower_sum+n-2*pp[x].dian_sum-pp[x].lower_sum;        pp[x].ans_sum=pp[x].border_sum+pp[x].lower_sum;    }    else    pp[x].ans_sum=pp[x].lower_sum;  //  cout<<x<<' '<<pp[x].dian_sum<<' '<<pp[x].lower_sum<<' '<<pp[x].border_sum<<' '<<pp[x].ans_sum<<endl;    for (int i=0;i<V[x].size();i++)    {        int v=V[x][i];        if (v==f) continue;        dfs_two(v,x);    }}int main(){    int a,b;    cin>>n;    for (int i=1;i<n;i++)    {        cin>>a>>b;        V[a].push_back(b);        V[b].push_back(a);    }    ans=0;    memset(pp,0,sizeof(pp));    dfs_one(1,-1);  //  cout<<"/n/n"<<endl;    dfs_two(1,-1);//    cout<<ans<<endl;    for (int i=1;i<=n;i++)        cout<<pp[i].ans_sum<<endl;    return 0;}

另外附一個求書上任意兩點之和的求解方法-.- (我開始把題意理解成了這個問題---寫好看了樣例發(fā)現(xiàn)不是這個問題  -.-  wwwwwww ).

即考慮每條邊的利用率----

每條邊的利用率為此邊下方的點個數(shù)N * 此邊上方的點個數(shù) M   * 2  -----   即下方到上方  和 上方到下方-----

代碼:

//每個邊的利用率為 n *  m ----   總和  --#include<cstdio>#include<cstring>#include<vector>#include<iostream>#include<algorithm>using namespace std;#define LL long longvector<int> V[100100];LL ans;int n;int dfs(int x,int f){    int he=1,k;    for (int i=0;i<V[x].size();i++)    {        if (V[x][i]==f)            continue;        k=dfs(V[x][i],x);        ans+=k*(n-k)*2;        he+=k;    }    return he;}int main(){    int a,b;    cin>>n;    for (int i=1;i<n;i++)    {        cin>>a>>b;        V[a].push_back(b);        V[b].push_back(a);    }    ans=0;    dfs(1,-1);    cout<<ans<<endl;    return 0;}


發(fā)表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發(fā)表
主站蜘蛛池模板: 军事| 同仁县| 巨鹿县| 西丰县| 富源县| 黄大仙区| 山丹县| 淮滨县| 古浪县| 张家港市| 托里县| 乐清市| 西充县| 麻阳| 广灵县| 高雄县| 阿城市| 上饶市| 沁源县| 同心县| 汝州市| 鄂尔多斯市| 普兰县| 江西省| 祥云县| 碌曲县| 康保县| 东海县| 平原县| 开封县| 天台县| 合肥市| 泽普县| 增城市| 龙海市| 南涧| 平顺县| 万全县| 闸北区| 仪征市| 三河市|