3522: [Poi2014]Hotel

来源:互联网 发布:linux nginx自动启动 编辑:程序博客网 时间:2024/05/14 20:59

3522: [Poi2014]Hotel

Time Limit: 20 Sec  Memory Limit: 128 MB
Submit: 572  Solved: 334
[Submit][Status][Discuss]

Description

有一个树形结构的宾馆,n个房间,n-1条无向边,每条边的长度相同,任意两个房间可以相互到达。吉丽要给他的三个妹子各开(一个)房(间)。三个妹子住的房间要互不相同(否则要打起来了),为了让吉丽满意,你需要让三个房间两两距离相同。
有多少种方案能让吉丽满意?

Input

第一行一个数n。
接下来n-1行,每行两个数x,y,表示x和y之间有一条边相连。

Output

让吉丽满意的方案数。

Sample Input

7
1 2
5 7
2 5
2 3
5 6
4 5

Sample Output

5

HINT

【样例解释】

{1,3,5},{2,4,6},{2,4,7},{2,6,7},{4,6,7}




【数据范围】

n≤5000

Source

By Dzy

[Submit][Status][Discuss]

对于每个合法方案,肯定能找到一个中点,这个点到另外三个点的距离都一样
枚举每个点当根,查询这个点作为中点的时候,合法方案的数量
以当前点为根dfs一遍,可以统计出所有深度为i的点的数量,当前点的每个儿子的子树中,深度为i的点的数量
对于当前点,枚举深度i从1到n,统计i的的答案
不过cmp函数,,,里面要写MaxL[x] > MaxL[y],,不知道为什么,写 >= 会无限RE。。。。
#include<iostream>#include<cstdio>#include<algorithm>#include<cmath>#include<cstring>#include<vector>#include<queue>#include<set>#include<map>#include<stack>#include<bitset>#include<ext/pb_ds/priority_queue.hpp>using namespace std;const int maxn = 5005;typedef long long LL;int n,Cnt,I,vis[maxn],L[maxn],cnt[maxn],f[maxn][maxn],B[maxn],C[maxn],MaxL[maxn];LL Ans;vector <int> v[maxn];bool cmp(const int &x,const int &y) {return MaxL[x] > MaxL[y];}void Dfs(int x,int y){++f[y][L[x]]; ++cnt[L[x]]; MaxL[y] = max(MaxL[y],L[x]);for (int i = 0; i < v[x].size(); i++){int to = v[x][i]; if (vis[to] == Cnt) continue;vis[to] = Cnt; L[to] = L[x] + 1; Dfs(to,y);}}void Work(int i){int tail = v[i].size() - 1;for (int j = 1; j <= n; j++){while (tail >= 0 && MaxL[v[i][tail]] < j) --tail; if (tail < 0) break; B[tail+1] = C[tail+1] = 0;for (int t = tail; t >= 0; t--){int son = v[i][t]; B[t] = f[son][j]; C[t] = f[son][j]*f[son][j];Ans += 1LL*(cnt[j]*B[t]*B[t+1] - C[t]*B[t+1] - B[t]*C[t+1]);B[t] += B[t+1]; C[t] += C[t+1];}}for (int j = 0; j < v[i].size(); j++){int son = v[i][j];for (int t = 1; t <= MaxL[son]; t++)f[son][t] = 0;}}int main(){#ifdef DMCfreopen("DMC.txt","r",stdin);#endifcin >> n;for (int i = 1; i < n; i++){int x,y; scanf("%d%d",&x,&y);v[x].push_back(y);v[y].push_back(x);}for (int i = 1; i <= n; i++){memset(cnt,0,sizeof(cnt)); vis[i] = ++Cnt;for (int j = 0; j < v[i].size(); j++){int to = v[i][j]; L[to] = 1; vis[to] = Cnt; MaxL[to] = 0; Dfs(to,to);}sort(v[i].begin(),v[i].end(),cmp); Work(i);}cout << Ans / 3LL;return 0;}

0 0