树上求和(dfs)
按照题目中的要求,只要统计每条边出现的次数,然后队次数排序,最后以后×n-1,n-2...1就行。
如何统计每个边出现的次数?(dfs)
比如边1,左边有两个顶点,右边有两个顶点。因此共包含边1 四次(2*2)。
1-2-3,1-2-3-4,2-3,2-3-4,四次,
所以我们只要统计每个边的左侧和右侧有多少顶点就可以。
#include<iostream> #include<vector> #include<string> #include<algorithm> #include<map> #include<climits> using namespace std; typedef long long ll; const int maxn=1e5+10; vector<int> g[maxn]; ll res[maxn],ans=0; bool visit[maxn]; int n,x,y;//输入 void init(int n){ for(int i=0;i<=n;i++){ res[i]=0; visit[i]=false; } }int cnt=0; ll dfs(int s){ visit[s]=true; ll num=1; for(int i=0;i<g[s].size();i++){ if(!visit[g[s][i]]){ num+=dfs(g[s][i]);//求每个点的左边顶点数 } } if(s!=1){ res[++cnt]=num*(n-num); //n-num为每个边的右边顶点数 } return num; } int main(){ cin>>n; init(n); for(int i=0;i<n-1;i++){ cin>>x>>y; g[x].push_back(y); g[y].push_back(x); } dfs(1); sort(res+1,res+1+cnt); for(int i=1;i<n;i++){ ans+=res[i]*(n-i); }cout<<ans<<endl; return 0; }