题意:
给你一棵n个顶点n-1条边的树,让你给n-1条边分别赋值1~n-1 ,每个数只能用一次,求整棵树最终任意两点之间的权值和。
题解:
我们只需要计算每条边被访问了多少次就行了,然后根据访问次数从小到大排序,最小的赋值最大的、…、最大的赋值最小的。
访问次数=该条边左边的端点数 * 该条边右边的端点数( size * (n-size) )
dfs找出每个顶点左边或者右边的个数,计算访问的次数,从小到大计算就ok了。
code:
#include<iostream>
#include<algorithm>
#include<cstring>
#include<map>
#include<queue>
#include<vector>
#include<set>
#include<sstream>
using namespace std;
typedef long long ll;
const ll maxn=1e6+10;
const ll inf=0x3f3f3f3f3f3f3f3f;
void io(){ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);}
ll he[maxn],ver[maxn],ne[maxn],vis[maxn];
ll size[maxn],ans[maxn];
ll cnt=0;
void add(ll x,ll y)
{
ver[++cnt]=y;
ne[cnt]=he[x];
he[x]=cnt;
}
void dfs(ll u)
{
size[u]=1;
for(int i=he[u];i;i=ne[i])
{
ll num=ver[i];
if(!vis[num])
{
vis[num]=1;
dfs(num);
size[u]+=size[num];
}
}
}
int main()
{
io();
ll n;
cin>>n;
for(int i=1;i<n;i++)
{
ll x,y;
cin>>x>>y;
add(x,y);
add(y,x);
}
vis[1]=1;
dfs(1);
for(int i=2;i<=n;i++)
ans[i]=size[i]*(n-size[i]);
sort(ans+2,ans+n+1);
ll sum=0;
for(int i=2;i<=n;i++)
sum+=ans[i]*(n-i+1);
cout<<sum<<endl;
return 0;
}