Y
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Others)Total Submission(s): 128 Accepted Submission(s): 41
Problem Description
Sample Input
4 1 2 1 3 1 4
Sample Output
1Hint1. The only set is {2,3,4}. 2. Please use #pragma comment(linker, "/STACK:16777216")
Source
Recommend
zhuyuanchen520
本题要求不存在欧拉路径的3的点的组合数。如果仅从排列组合的角度,本题是不好解的,可以换种求补的思想。正难则反。
所求=总的组合数-存在欧拉路径的3的点的组合数。由于本题是图,所以可以考虑在遍历的过程中求解。题目提示栈,所以用DFS。
若遍历到某一节点u,某时刻假设以u为根节点的已经遍历过的子孙节点的数目为tmp,我们正DFS u的一颗子树v(num[v]),则此时新加的存在欧拉路径的3的点的组合数为tmp*num[v],tmp+=num[v],即与v不同一分支的任一结点,u和分支v上的任一节点三者肯定存在欧拉路径。此外以u为根节点的任一结点、u和树上的不在u这棵子树的其他任一节点都可组成欧拉路径,于是又新添tmp*(n-num[u]).
#include<iostream>
#include<cstring>
#include<cstdio>
#pragma comment(linker, "/STACK:16777216")
using namespace std;
//***************************************************
const int MAXN=100000+100;//定义顶点个数
struct Node
{
int to;
int next;
}edge[MAXN*2];//存放边信息,邻接表的边最多为2倍的顶点数
int head[MAXN];//存放节点信息,邻接表的简易实现方案
int tol,n;
void add(int a,int b)
//建立a->b的有向边函数
{
edge[tol].to=b;
edge[tol].next=head[a];
head[a]=tol++;
}
void init()
//初始化函数
{
tol=0;//顶点个数
memset(head,-1,sizeof(head));//初始化头顶点都无边
}
//***************************************************
__int64 op_ans;
__int64 num[MAXN];
void DFS(int cur,int pre)
{
int i;
num[cur]=1;
__int64 tmp=0;
for(i=head[cur];i!=-1;i=edge[i].next)
{
int u=edge[i].to;
if(u==pre)continue;
DFS(u,cur);
op_ans+=tmp*num[u];
tmp+=num[u];
num[cur]+=num[u];
}
op_ans+=tmp*((__int64)n-num[cur]);
}
int main()
{
int i,s,e;
while(~scanf("%d",&n))
{
init();
for(i=0;i<n-1;i++)
{
scanf("%d%d",&s,&e);
add(s,e);
add(e,s);
}
op_ans=0;
DFS(2,-1);
printf("%I64d\n",(__int64)n*(n-1)*(n-2)/6-op_ans);
}
return 0;
}