树基于点的分治
来源:互联网 发布:linux php 写入权限 编辑:程序博客网 时间:2024/05/16 14:05
除转载的四道例题外,还有
hdu 4670
******************************************************分割线,接下来是代码**************************************************
//BZOJ 2599//点按[1,n]存,0有特殊用#include <cstdio>#include <algorithm>#include <vector>#include <cstring>using namespace std;#define N 200005#define C 1000005struct edge{ int to,next,w;}e[N<<1];int n,m;int root,size,ans,o;int s[N],f[N],d[N],ee[N],head[N],c[C],v[C];vector<int> dep;bool done[N];void add(int x,int y,int z){ e[o].to=y; e[o].w=z; e[o].next=head[x]; head[x]=o++;}void getroot(int now, int fa) { int u; s[now] = 1; f[now] = 0; for (int i=head[now]; ~i; i=e[i].next) if ((u =e[i].to)!= fa) { if (done[u]) continue; getroot(u, now); s[now] += s[u]; f[now] = max(f[now], s[u]); } f[now] = max(f[now], size-s[now]); if (f[now] < f[root]) root = now;}void dfs1(int now, int fa) { int u; if (d[now] > m) return; if (v[m-d[now]] == root) ans=min(ans,c[m-d[now]] + ee[now]); for (int i = head[now]; ~i; i = e[i].next) if ((u =e[i].to)!= fa) { if (done[u]) continue; d[u] = d[now] + e[i].w; ee[u] = ee[now] + 1; dfs1(u, now); }}void dfs2(int now, int fa) { int u; if (d[now] > m) return; if (v[d[now]] != root) { c[d[now]] = ee[now]; v[d[now]] = root; } else c[d[now]]=min(c[d[now]],ee[now]); for (int i = head[now]; ~i; i = e[i].next) if ((u =e[i].to)!= fa) { if (done[u]) continue; dfs2(u, now); }}void work(int now) { int u; v[0]=root; done[now] = true; for (int i=head[now]; ~i; i=e[i].next) if (!done[u =e[i].to]) { d[u] = e[i].w; ee[u] = 1; dfs1(u, now); dfs2(u, now); } for (int i=head[now]; ~i; i=e[i].next) if (!done[u =e[i].to]) { f[0] = size = s[u]; getroot(u, root=0); work(root); }}void doit(){ ans = n; memset(done, 0, sizeof(done)); memset(head,255,sizeof(head)); o=0; for (int i=1,x,y,w; i<n; i++) { scanf("%d%d%d", &x, &y, &w);x++; y++; add(x,y,w); add(y,x,w); } f[0] = size = n; getroot(1, root=0); work(root); printf("%d\n", ans < n ? ans : -1);}int main(){ while (scanf("%d%d",&n,&m)!=EOF) doit(); return 0;}/*4 30 1 11 2 21 3 4*/
//Hdu 4670#pragma comment(linker, "/STACK:1024000000,1024000000")#include <cstdio>#include <algorithm>#include <vector>#include <cstring>#include <map>using namespace std;#define N 50005#define C 100005#define T 32typedef long long LL;struct edge{ int to,next;}e[N<<1];int n,root,size,o,pr,equ,oo;LL ans,total[T];map<LL,int> mm;int s[N],f[N],d[N][T],head[N],c[C];LL res[C];LL pri[T];vector<int> dep;bool done[N];int num[N][T];void add(int x,int y){ e[o].to=y; e[o].next=head[x]; head[x]=o++;}void getroot(int now, int fa) { int u; s[now] = 1; f[now] = 0; for (int i=head[now]; ~i; i=e[i].next) if ((u =e[i].to)!= fa) { if (done[u]) continue; getroot(u, now); s[now] += s[u]; f[now] = max(f[now], s[u]); } f[now] = max(f[now], size-s[now]); if (f[now] < f[root]) root = now;}void dfs(int now,int fa){ int tmp,u; LL s1=0,s2=0; for (int i=0;i<pr;i++) { d[now][i]=d[fa][i]+num[now][i]; if (d[now][i]>2) d[now][i]-=3; tmp=(total[i]+3-d[now][i])%3; s1=s1*3+d[now][i]; s2=s2*3+tmp; } if (s1==s2) equ++; if (mm.find(s1)==mm.end()) {mm[s1]=oo;res[oo]=s2;c[oo++]=1;}else {c[mm[s1]]++;} for (int i=head[now];~i;i=e[i].next) if ((u=e[i].to)!=fa) { if (done[u]) continue; dfs(u, now); }}LL calc(int now,int fa){ mm.clear();//memset(c,0,sizeof(c)); 加上这句会T equ=0; oo=0; if (fa) for (int i=0;i<pr;i++) total[i]=num[fa][i]; else for (int i=0;i<pr;i++) total[i]=num[now][i]; dfs(now,fa); LL re=0; for (int i=0;i<oo;i++) { if (mm.find(res[i])!=mm.end()) re+=c[i]*c[mm[res[i]]]; } return (re-equ)/2+equ;}void work(int now) { int u; done[now] = true; ans+=calc(root,0); for (int i=head[now]; ~i; i=e[i].next) if (!done[u =e[i].to]) { ans-=calc(u,now); f[0] = size = s[u]; getroot(u, root=0); work(root); }}void doit(){ ans = 0; memset(done, 0, sizeof(done)); scanf("%d",&pr); for (int i=0;i<pr;i++) scanf("%I64d",&pri[i]); memset(num,0,sizeof(num)); for (int i=1;i<=n;i++) { LL x; scanf("%I64d",&x); for (int j=0;j<pr;j++) { while (x%pri[j]==0) { x/=pri[j]; num[i][j]++; } num[i][j]%=3; } } memset(head,255,sizeof(head)); o=0; for (int i=1,x,y; i<n; i++) { scanf("%d%d", &x, &y); add(x,y); add(y,x); } f[0] = size = n; getroot(1, root=0); work(root); printf("%I64d\n",ans);}int main(){ while (scanf("%d",&n)!=EOF) doit(); return 0;}/*42 2 5100 10 100 101 22 33 471 22 2 2 2 2 2 21 21 32 42 53 63 753 2 3 52500 200 9 270000 274 23 52 54 163 2 3 56 1 30 150 150 121 22 41 33 53 6ans:4714*/
0 0
- 树基于点的分治
- [基于树的点分治]POJ 2114
- 【转】树基于点的分治
- 树上基于点的分治
- 树的分治-点分治
- 树的点分治
- 树的点分治
- POJ1741树的分治之点分治
- 树分治-点分治
- 初识点剖(基于点的树上分治)
- poj1741 树的点分治
- 【树的点分治】阴阳
- poj2114(树的点分治)
- CV1873 树的点分治
- 浅谈树的点分治
- poj1987 树的点分治
- UVA6642(树的点分治)
- POJ1741——Tree 基于点的分治
- MFC文档视图(一):简介
- Android开发之自动补全文本框
- 第五周(项目一 1)——三角形类的构造函数
- 分块查找
- Cracking the coding interview--Q16.1-Q16.10
- 树基于点的分治
- [LeetCode]Binary Tree Postorder Traversal
- 进程调度(一)--linux内核设计与实现读书笔记
- C++拷贝构造函数详解
- 红黑树的插入
- MFC文档视图(三):命令消息路由
- 红黑树的删除
- 位运算
- 求正整数n以内的所有素数