博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
图论:点分治
阅读量:4600 次
发布时间:2019-06-09

本文共 2412 字,大约阅读时间需要 8 分钟。

点分治我感觉是图论树部分比较考验脑力的一种题目了

POJ1741

题意:给一棵边带权树,问两点之间的距离小于等于K的点对有多少个

满足条件的点对有两种情况:两个点的路径横跨树根,两个点位于同一颗子树中

对于根节点进行一次dfs,求出deep,并将其从小到大排序

void getdeep(int x,int fa){    dep[++dep[0]]=d[x];    for(int tmp=g[x];tmp;tmp=e[tmp].next)    {        if(e[tmp].t==fa||vis[e[tmp].t]) continue;        d[e[tmp].t]=d[x]+e[tmp].v;        getdeep(e[tmp].t,x);    }}

然后看一下calculate

int cal(int x,int tmp){    d[x]=tmp;dep[0]=0;    getdeep(x,0);    sort(dep+1,dep+dep[0]+1);    int t=0,l,r;    for(l=1,r=dep[0];l

如果我们已经知道了此时所有点到根的距离a[i]

a[x] + a[y] <= k的(x, y)对数就是结果,这个可以通过排序之后O(n)的复杂度求出

然后根据分治的思想,分别对所有的儿子求一遍即可

void work(int x)  //点分治 {    ans+=cal(x,0);    vis[x]=1;    for(int tmp=g[x];tmp;tmp=e[tmp].next)    {        if(vis[e[tmp].t]) continue;        ans-=cal(e[tmp].t,e[tmp].v);        sum=ch[e[tmp].t];        root=0;        getroot(e[tmp].t,root);        work(root);    }}

但是这会出现重复的——当前情况下两个点位于一颗子树中,那么应该将其减掉

显然这两个点是满足题意的,为什么减掉呢?因为在对子树进行求解的时候,会重新计算

在进行分治时,为了避免树退化成一条链而导致时间复杂度变为O(N^2),每次都找树的重心

这样,所有的子树规模就会变的很小了。时间复杂度O(Nlog^2N)

void getroot(int x,int fa){    ch[x]=1;f[x]=0;    for(int tmp=g[x];tmp;tmp=e[tmp].next)    {        if(e[tmp].t==fa||vis[e[tmp].t]) continue;        getroot(e[tmp].t,x);        ch[x]+=ch[e[tmp].t];        f[x]=max(f[x],ch[e[tmp].t]);    }    f[x]=max(f[x],sum-ch[x]);    if(f[x]

有了板子不能救命,还要大量刷大量刷才可以,点分治确实是一个要命的地方,上次的省赛的一道题就栽了

1 #include
2 #include
3 #include
4 using namespace std; 5 const int maxn=10005; 6 const int maxm=20005; 7 const int INF=0x7fffffff; 8 int n,k,ans; 9 int cnt,g[maxn]; 10 struct Edge{
int t,next,v;}e[maxm]; 11 12 int root,sum; 13 int ch[maxn],f[maxn],dep[maxn],d[maxn]; 14 bool vis[maxn]; 15 16 void addedge(int u,int v,int w) 17 { 18 cnt++; 19 e[cnt].t=v;e[cnt].v=w; 20 e[cnt].next=g[u];g[u]=cnt; 21 } 22 int read() 23 { 24 int x=0,f=1;char ch=getchar(); 25 while(ch<'0'||ch>'9') {
if(ch=='0')f=-1;ch=getchar();} 26 while(ch>='0'&&ch<='9') {x=x*10+ch-'0';ch=getchar();} 27 return x*f; 28 } 29 void getroot(int x,int fa) 30 { 31 ch[x]=1;f[x]=0; 32 for(int tmp=g[x];tmp;tmp=e[tmp].next) 33 { 34 if(e[tmp].t==fa||vis[e[tmp].t]) continue; 35 getroot(e[tmp].t,x); 36 ch[x]+=ch[e[tmp].t]; 37 f[x]=max(f[x],ch[e[tmp].t]); 38 } 39 f[x]=max(f[x],sum-ch[x]); 40 if(f[x]

 

转载于:https://www.cnblogs.com/aininot260/p/9461358.html

你可能感兴趣的文章
.net 编译原理
查看>>
mean 快速开发和现有技术的对比分析
查看>>
Metro Style app :浏览器扩展
查看>>
linux的kernel是怎样工作的(TI_DM36X_ARM系统)(1)
查看>>
[luogu4310] 绝世好题 (递推)
查看>>
[luogu3203 HNOI2010] 弹飞绵羊 (分块)
查看>>
-Dmaven.multiModuleProjectDirectory system propery is not set.
查看>>
Python2 unichr() 函数
查看>>
Python 字典 copy()方法
查看>>
Minimum Path Sum
查看>>
Remove Duplicates from Sorted Array II
查看>>
常量指针和指针常量巧妙记忆方法[转]
查看>>
python-haproxy作业讲解视频总结
查看>>
批处理文件脚本总结
查看>>
快速排序C++代码
查看>>
mui搜索框 搜索点击事件
查看>>
bzoj 5289: [Hnoi2018]排列
查看>>
joomla处境堪忧
查看>>
Jquery-AJAX
查看>>
mysql命令gruop by报错this is incompatible with sql_mode=only_full_group_by
查看>>