列表

详情


NC50097. 滑稽树下你和我

描述

红红和蓝蓝是随机降生在苹果树上的苹果仙灵,现在红线仙想估测他们的CP系数,并决定是否使他们成为一对CP。
给出n个结点n-1条边的树,节点编号为1到n,定义distance(i,j)为i与j的树上距离。
CP系数是指所有红红和蓝蓝在不同位置i,j的distance(i,j)之和。
即 
求红红和蓝蓝的CP系数,对109+7取模。

输入描述

第一行一个整数n( 1 < n <= 105 ),表示树的结点个数。
随后n-1行,每行三个整数a,b,c ( 1 <= a,b <= n ),( 0 <= c <= 109 ),表示结点a,b之间有一条权值为c的边,( a  b )。

输出描述

一行一个整数,表示CP系数对109+7取模的结果。

示例1

输入:

4
1 2 1
2 3 1
2 4 1

输出:

9

说明:

distance(1,2)=1
distance(1,3)=2
distance(1,4)=2
distance(2,3)=1
distance(2,4)=1
distance(3,4)=2
CP系数=(1+2+2+1+1+2)%(109+7)=9

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++14(g++5.4) 解法, 执行用时: 66ms, 内存消耗: 4068K, 提交时间: 2019-07-14 17:37:38

#include<bits/stdc++.h>
using namespace std;
const int N=4e5+10;
const int M=1e9+7;
int head[N],Next[N],edge[N],ver[N],num[N],n,tot;
long long ans;
void add(int x,int y,int z){
    ver[++tot]=y;edge[tot]=z;Next[tot]=head[x];head[x]=tot;
}
void dfs(int x,int y){
    num[x]=1;
    for(int i=head[x];i;i=Next[i]){
        if(ver[i]==y)continue;
        dfs(ver[i],x);
        num[x]+=num[ver[i]];
        ans=(ans+1ll*num[ver[i]]*(n-num[ver[i]])%M*edge[i]%M)%M;
    }
}
int main(){
    int x,y,z;cin>>n;
    for(int i=1;i<n;++i)scanf("%d%d%d",&x,&y,&z),add(x,y,z),add(y,x,z);
    dfs(1,0);
    cout<<ans<<endl;
}

C++11(clang++ 3.9) 解法, 执行用时: 129ms, 内存消耗: 10072K, 提交时间: 2019-06-22 13:00:35

#include<bits/stdc++.h>
#define maxn 100005
#define mod 1000000007
using namespace std;
typedef long long ll;
ll n;
ll sum;
vector<pair<ll,ll> >mp[maxn];
ll dp[maxn];
void dfs(ll x,ll f){
	dp[x]=1;
	for(int i=0;i<mp[x].size();i++){
		ll v=mp[x][i].first;
		if(v==f) continue;
		dfs(v,x);
		sum=(sum+(n-dp[v])*dp[v]%mod*mp[x][i].second)%mod;
		dp[x]+=dp[v];
	}
}
int main(){
	cin>>n;
	ll a,b,c;
	for(int i=0;i<n-1;i++){
		cin>>a>>b>>c;
		mp[a].push_back(make_pair(b,c));
		mp[b].push_back(make_pair(a,c));
	}
	dfs(1,-1);
	cout<<sum;
}

上一题