hdu 4705 Y/杭电2013年多校第十场1010 组合
来源:互联网 发布:php沐辰的博客 编辑:程序博客网 时间:2024/05/18 18:53
#pragma comment(linker, "/STACK:16777216")#include <cstdio>#include <cstring>#include <cmath>#include <vector>#include <algorithm>#include <iostream>using namespace std;#define LL __int64#define maxn 100011const int mod=1e9+7;vector<int>e[maxn];int c[maxn],d[maxn];int dfs(int pre,int u)//以1为根结点{ c[u]=1;//记录点的子树结点数和+1 d[u]=pre;//记录父节点 int i,v; if(e[u].size()==1&&e[u][0]==pre) return c[u]; for(i=0;i<e[u].size();i++) { v=e[u][i]; if(v==pre)continue; c[u]+=dfs(u,v); } return c[u];}int main(){ int n; while(scanf("%d",&n)!=EOF) { int i,j,k,a,b; for(i=1;i<=n;i++) e[i].clear(); for(i=1;i<n;i++) { scanf("%d%d",&a,&b); e[a].push_back(b); e[b].push_back(a); } dfs(-1,1); /*for(i=1;i<=n;i++) cout<<c[i]<<" "; cout<<endl;*/ int v,u; LL ans=0,s; for(i=1;i<=n;i++) { s=0; if(e[i].size()==1)continue; for(j=0;j<e[i].size();j++) { v=e[i][j]; if(v==d[i])a=n-c[i]; else a=c[v]; b=n-a-1; //a为左符合点数,b为右符合点数 s+=(LL)a*b; } ans+=s/2; } //cout<<ans<<endl; ans=(LL)n*(n-1)*(n-2)/6-ans; printf("%I64d\n",ans); } return 0;}/*样例:Input:31 22 361 22 42 51 33 6Output:03 方法:找到符合要求的三个点的方案数ans,答案就是C(n,3)-ans; 枚举所有结点,以这个结点为中符合点的所有方案数和就是ans 对于一个结点,在一棵子树上找一个点做左符合点,则其余子树上的点都右符合点。 举例来说,一个点有三个子树,子树结点数分别为1,2,3,则符合要求的组合有(1*5+2*4+3*3)/2(会重复一次) */