【BZOJ】【3522】【POI2014】Hotel
暴力/树形DP
要求在树上找出等距三点,求方案数,那么用类似Free Tour2那样的合并方法,可以写出:
f[i][j]表示以 i 为根的子树中,距离 i 为 j 的点有多少个;
g[i][j]表示以 i 为根的子树中,选出两点,剩下那点距离 i 为 j 的方案数;
那么就可以在搜索完一棵子树的时候用g[i]和f[to[i]]更新答案,然后更新f[i]和g[i],最后还要考虑g[i]和祖先的配对情况……
但是我写跪了= =后来一看题解……$N\leq 5000$!!!直接$N^2$暴力啊,搞什么树形DP啊……
强行枚举中间点数方案就好了……数方案的方法跟之前树形DP时一样,只不过只在选出来的根那里做……
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 /************************************************************** 2 Problem: 3522 3 User: Tunix 4 Language: C++ 5 Result: Accepted 6 Time:7168 ms 7 Memory:1452 kb 8 ****************************************************************/ 9 10 //BZOJ 3522 11 #include<vector> 12 #include<cstdio> 13 #include<cstring> 14 #include<cstdlib> 15 #include<iostream> 16 #include<algorithm> 17 #define rep(i,n) for(int i=0;i<n;++i) 18 #define F(i,j,n) for(int i=j;i<=n;++i) 19 #define D(i,j,n) for(int i=j;i>=n;--i) 20 #define pb push_back 21 using namespace std; 22 inline int getint(){ 23 int v=0,sign=1; char ch=getchar(); 24 while(ch<'0'||ch>'9'){ if (ch=='-') sign=-1; ch=getchar();} 25 while(ch>='0'&&ch<='9'){ v=v*10+ch-'0'; ch=getchar();} 26 return v*sign; 27 } 28 const int N=5010,INF=~0u>>2; 29 typedef long long LL; 30 /******************tamplate*********************/ 31 int to[N*2],next[N*2],head[N],cnt; 32 void ins(int x,int y){to[++cnt]=y; next[cnt]=head[x]; head[x]=cnt;} 33 void add(int x,int y){ins(x,y); ins(y,x);} 34 35 bool vis[N]; 36 int n,f[N],g[N],tmp[N],dep[N]; 37 LL ans; 38 void dfs(int x,int fa){ 39 tmp[dep[x]]++; 40 for(int i=head[x];i;i=next[i]) 41 if(to[i]!=fa){ 42 dep[to[i]]=dep[x]+1; 43 dfs(to[i],x); 44 } 45 } 46 47 int main(){ 48 #ifndef ONLINE_JUDGE 49 freopen("3522.in","r",stdin); 50 freopen("3522.out","w",stdout); 51 #endif 52 n=getint(); 53 int x,y; 54 F(i,2,n){ 55 x=getint(); y=getint(); 56 add(x,y); 57 } 58 F(x,1,n){ 59 memset(g,0,sizeof g); 60 memset(f,0,sizeof f); 61 for(int i=head[x];i;i=next[i]){ 62 memset(tmp,0,sizeof tmp); 63 dep[to[i]]=1; 64 dfs(to[i],x); 65 F(j,1,n){ 66 ans+=(LL)g[j]*tmp[j]; 67 g[j]+=f[j]*tmp[j]; 68 f[j]+=tmp[j]; 69 } 70 } 71 } 72 printf("%lld\n",ans); 73 return 0; 74 }
3522: [Poi2014]Hotel
Time Limit: 20 Sec Memory Limit: 128 MBSubmit: 251 Solved: 116
[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
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