您的位置:首页 > 其它

【汕头市选2014】分叉 jzoj 3630 dfs

2018-01-31 12:30 239 查看

题目

给出一棵N 个点的树,点的编号是1, 2,。。。,N。

对于3 个点{a,b,c},如果不存在一条简单路径同时经过a,b,c,那么{a,b,c}是一个分叉。

统计不同分叉的数量。

分析

比赛时爆int.

开了long long就对了

我们可以很方便的找到有一条简单路径经过{x,y,z}三元组的个数

然后拿所有的三元组个数去减就好了.

code

#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<string>
#include<algorithm>
#define maxn 200005
#define maxm 300005
#define INF 0x7fffffff;

using namespace std;

struct arr{
int x,y;
int next;
}edge[maxm];
int ls[maxn];
int edge_m;

long long son[maxn];
long long f[maxn];

long long n;

void add(int x,int y)
{
edge[++edge_m]=(arr){x,y,ls[x]},ls[x]=edge_m;
edge[++edge_m]=(arr){y,x,ls[y]},ls[y]=edge_m;
}

int dfs(int x,int r)
{
son[x]=1;
for (int i=ls[x];i;i=edge[i].next)
{
if (edge[i].y==r) continue;
dfs(edge[i].y,x);
son[x]+=son[edge[i].y];
}
int num=1;
for (int i=ls[x];i;i=edge[i].next)
{
if (edge[i].y==r) continue;
num+=son[edge[i].y];
f[x]+=son[edge[i].y]*(n-num);
}
}

int main()
{
freopen("fork.in","r",stdin);
freopen("fork.out","w",stdout);
scanf("%d",&n);
for (int i=1;i<n;i++)
{
int x,y;
scanf("%d%d",&x,&y);
add(x,y);
}
dfs(1,0);
long long ans=(long long)(n*(n-1)*(n-2)/6);
for (int i=1;i<=n;i++)
{
ans-=f[i];
}
cout<<ans;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: