Y
题意:给你一棵树,n个节点n-1条边(双向),树上任意三个点不在一条路径上,统计这样的三点集合有多少种。
思路:
n个节点中任选3个点的方案数为n*(n-1)*(n-2)/6,从中减去三个点在同一条路径上的种类数即为答案。如何找在同一条路径上的方案数呢,就是以固定某一个点,看看他的一个儿子有几个儿子,儿子的儿子个数加上儿子本身,从这些点中选一个,再从剩余的点中选一个,即可以构成三个点在同一条直线上。所有对于固定的这个点x,方案数为sum[son]*(n-sum[x])
#include<iostream> #include<cstdio> #include<cstring> #include<vector> #include<algorithm> using namespace std; typedef long long ll; const int maxn=1e5+10; vector<int>v[maxn]; int vis[maxn]; int a,b; ll ans,n,t,son[maxn]; void dfs(int x) { vis[x]=1; son[x]=1; for(int i=0;i<v[x].size();i++) { int to=v[x][i]; if(vis[to]) continue; dfs(to); son[x]+=son[to]; ans+=(n-son[x])*son[to]; } } int main() { while(~scanf("%lld",&n)) { ans=0; memset(son,0,sizeof(son)); memset(vis,0,sizeof(vis)); for(int i=0;i<=n;i++) v[i].clear(); for(int i=1;i<n;i++) { scanf("%d%d",&a,&b); v[a].push_back(b); v[b].push_back(a); } dfs(1); t=(n-1)*n*(n-2)/6; printf("%lld\n",t-ans); } }
这个题的思路和hdu2376有些像,果然要学着举一反三啊啊啊啊啊啊~~~
原文地址:https://www.cnblogs.com/1013star/p/9960043.html
时间: 2024-10-18 09:38:50