快乐树论

Description

 曾经有一位伟大的皇帝,他拥有n座城池并用n-1条无向道路相连,每条道路均有一个确定的长度和两个端点,保证城池与城池之间互达。有一天,皇帝决定将其中一条路拆掉,并重新将这条道路以同样的长度搭在两座城池之间,皇帝可能将这条路拆了又重新建在原处。现在皇帝想问问你,在只拆掉一条道路并重新建造一条同样长的在两座城池之间后,任意两个城池之前的距离和最小为多少呢?

 

Input

 第一行输入一个n代表皇帝有n座城池,接下来n-1行输入a,b,c代表城池a,b之间有一条长为c的道路。 (2 ≤ n ≤ 5000, 1 ≤ ai, bi ≤ n, ai ≠ bi, 1 ≤ wi ≤ 106)

 

Output

 输出一行任意两城池之间的最小距离和。

 

Sample Input

输入样例1: 3 1 2 2 1 3 4 输入样例2: 6 1 2 1 2 3 1 3 4 1 4 5 1 5 6 1 输入样例3: 6 1 3 1 2 3 1

Sample Output

输出样例1: 12 输出样例2: 29 输出样例3: 825

HINT

 

 实际输入输出中并没有“输入样例1”, “输出样例1:” 之类 这种东西,这里只是为了多给几组数据,让大家更容易的理解用的

题解:

具体证明参考:https://blog.csdn.net/zhoufenqin/article/details/9821617

#include<bits/stdc++.h>

#define fi first
#define se second
#define pb push_back

using namespace std;

typedef long long ll;
typedef pair<ll,ll> Pll;

const ll LLMAX=2e18;
const int MAXN=1e6+10;

struct node{
    int u,v;
    ll w;
}in[MAXN];

ll dp[MAXN][3];
vector<Pll>G[MAXN];

void dfs(int u,int pre){
    dp[u][0]=dp[u][1]=dp[u][2]=0;
    for(int i=0;i<G[u].size();i++){
        int v=G[u][i].fi,w=G[u][i].se;
        if(v==pre)   continue;
        dfs(v,u);
        dp[u][2]+=dp[v][2]+dp[v][1]*dp[u][0]+dp[v][0]*dp[u][1]+dp[u][0]*dp[v][0]*w;
        dp[u][1]+=dp[v][1]+dp[v][0]*w;
        dp[u][0]+=dp[v][0];            
    }
    dp[u][0]++;
    dp[u][2]+=dp[u][1];
}

void solve(int u,int pre,ll &ans){
    ans=min(ans,dp[u][1]);
    for(int i=0;i<G[u].size();i++){
        int v=G[u][i].fi,w=G[u][i].se;
        if(v==pre)  continue;
        dp[v][1]=dp[v][1]+(dp[u][1]-dp[v][1]-w*dp[v][0])+(dp[u][0]-dp[v][0])*w;
        dp[v][0]=dp[u][0];
        solve(v,u,ans);
    }
}

int main(void)
{
    ios::sync_with_stdio(false);    cin.tie(0);
    ll n,ans=LLMAX;  cin>>n; 
    for(int i=1;i<n;i++){
        ll x,y,v;  cin>>x>>y>>v;    
        in[i].u=x,in[i].v=y,in[i].w=v;
        G[x].pb(Pll(y,v)),G[y].pb(Pll(x,v));
    }
    for(int i=1;i<n;i++){
        ll ans1=LLMAX,ans2=LLMAX,u=in[i].u,v=in[i].v,w=in[i].w;
        dfs(u,v);   solve(u,v,ans1);
        ll len1=(n-dp[u][0])*ans1+dp[u][2];
        dfs(v,u);   solve(v,u,ans2);
        ll len2=(n-dp[v][0])*ans2+dp[v][2];
        ans=min(ans,len1+len2+dp[u][0]*dp[v][0]*w);
    }
    cout<<ans<<endl;
    return 0;
}

 

全部评论

相关推荐

牛客410815733号:这是什么电影查看图片
点赞 评论 收藏
分享
评论
点赞
收藏
分享
正在热议
# 25届秋招总结 #
443000次浏览 4514人参与
# 春招别灰心,我们一人来一句鼓励 #
42077次浏览 535人参与
# 北方华创开奖 #
107454次浏览 600人参与
# 地方国企笔面经互助 #
7969次浏览 18人参与
# 同bg的你秋招战况如何? #
77008次浏览 566人参与
# 实习必须要去大厂吗? #
55786次浏览 961人参与
# 阿里云管培生offer #
120345次浏览 2220人参与
# 虾皮求职进展汇总 #
115973次浏览 886人参与
# 如果你有一天可以担任公司的CEO,你会做哪三件事? #
11650次浏览 289人参与
# 实习,投递多份简历没人回复怎么办 #
2454867次浏览 34858人参与
# 提前批简历挂麻了怎么办 #
149922次浏览 1978人参与
# 在找工作求抱抱 #
906063次浏览 9421人参与
# 如果公司给你放一天假,你会怎么度过? #
4762次浏览 55人参与
# 你投递的公司有几家约面了? #
33209次浏览 188人参与
# 投递实习岗位前的准备 #
1196011次浏览 18550人参与
# 机械人春招想让哪家公司来捞你? #
157640次浏览 2267人参与
# 双非本科求职如何逆袭 #
662310次浏览 7397人参与
# 发工资后,你做的第一件事是什么 #
12786次浏览 62人参与
# 工作中,努力重要还是选择重要? #
35857次浏览 384人参与
# 简历中的项目经历要怎么写? #
86934次浏览 1516人参与
# 参加完秋招的机械人,还参加春招吗? #
20142次浏览 240人参与
# 我的上岸简历长这样 #
452046次浏览 8089人参与
牛客网
牛客企业服务