单点时限: 1.0 sec
内存限制: 512 MB
Jerry给Tom出了一道题,题目是这样的:
**给出一棵n个节点的树,节点编号为1-n(根节点编号为1),每一个节点作为根节点与他所有的子孙节点形成一棵子树,而这棵子树包含节点的数量,称作子树的Size。
例如:
1─2─4─5
└─3
其中节点5的子树只包括节点5,Size = 1。节点4的子树包括节点4,5,Size = 2。节点1的子树包括节点1,2,3,4,5,Size = 5。
求以所有节点为根的子树的Size之和。上面例子中,节点1到5,对应的Size分别为5,3,1,2,1,所有Size的和 = 5 + 3 + 1 + 2 + 1 = 12
输入格式
第一行:1个数n(1 < n <= 10000),表示树的节点数量。
后面n-1行:每行2个数x y,表示节点x是节点y的父节点(1 <= x, y <= n)。
输出格式
输出1个数,表示以所有节点为根的子树的Size之和。
样例
input
4
1 2
1 3
2 4
output
8
思路:
首先用vector pair把图存进来,然后暴力枚举对每一个点进行bfs,找他的子树的size;再加上记忆化搜索,就不会超时了!
AC代码:
#include <bits/stdc++.h>
using namespace std;
vector<pair<int,int> > v[10010];
int dp[10010];
int ans;
int bfs(int n)
{
ans=1;
queue<int> q;
int h=n;
q.push(h);
while(!q.empty())
{
h=q.front();
q.pop();
pair<int,int> n;
for(int i=0;i<v[h].size();i++)
{
n=v[h][i];
if(dp[n.first]>0&&n.second==1)
{
ans+=dp[n.first];
continue;
}
if(n.second==1)
{
ans++;
q.push(n.first);
}
}
}
return ans;
}
int main()
{
int n;
cin >>n;
int x,y;
for(int i=1;i<n;i++)
{
cin >>x>>y;
v[x].push_back(make_pair(y,1));
v[y].push_back(make_pair(x,-1));
}
int sum=0;
for(int i=1;i<=n;i++)
{
dp[i]=bfs(i);
sum+=dp[i];
}
cout <<sum<<endl;
return 0;
}