您的位置:首页 > 其它

JZOJ3630. 【汕头市选2014】分叉(fork)

2017-02-25 15:58 274 查看
Description

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

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

统计不同分叉的数量。

树 无环,连通的无向图

简单路径 不重复经过同一个点的路径

Input

第1 行,1 个整数N。接下来(N -1) 行,每行2 个整数Ai,Bi,表示点Ai 和点Bi 间有一条边。

Output

1 个整数,表示所求的值。

Sample Input

5

1 2

1 3

1 4

1 5

Sample Output

4

Data Constraint

• 对于30% 的数据,N <= 100;

• 对于50% 的数据,N <= 1000;

• 对于100% 的数据,1 <= N <= 10^5。

分析:简单的组合数学。。不合法的方案就直接每个子树之间统计答案,一边走,统计size,然后一边乘,最后把上面的和子树乘一下就行了。然后用总方案减去不合法方案。

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#define fd(i,a,b) for(int i=a;i>=b;i--)
#define fo(i,a,b) for (int i=a;i<=b;i++)
using namespace std;
const int N=200005;
typedef long long ll;
int n,m,tot,root;
int head
,go[N*2],next[N*2],size
,fa
;
int b
,c
;
ll ans,cnt;
void add(int x,int y)
{
go[++tot]=y;
next[tot]=head[x];
head[x]=tot;
}
void dfs1(int x)
{
size[x]=1;
for (int i=head[x];i;i=next[i])
if (go[i] != fa[x])
{
fa[go[i]]=x;
dfs1(go[i]);
size[x] += size[go[i]];
}
}
void dfs(int x)
{
cnt=0;
for (int i=head[x];i;i=next[i])
{
ans+=(ll)cnt*size[go[i]];
cnt+=size[go[i]];
}
b[x]=size[x];
for (int i=head[x];i;i=next[i])
if (go[i]!=fa[x])
{
size[x]=b[x];
c[x]=size[go[i]];
size[x]-=size[go[i]];
size[go[i]]+=size[x];
dfs(go[i]);
size[go[i]]=c[x];
}
}

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