【题解】POJ 3417 Network(倍增求LCA+DP+树上差分)
POJ3417:http://poj.org/problem?id=3417
思路
我们注意到由“主要边”构成一颗树 “附加边”则是非树边 把一条附加边(x,y)加入树中 会与树上x,y之间构成一个环
因此 我们称每条附加边(x,y)都把树上x,y之间的路径覆盖一次 我们只需要统计出每条“主要边”被覆盖几次
有以下几种情况
- 第一步把覆盖0次的主要边切断 则第二步可以任意切一条附加边 ans+=m
- 第一步把覆盖1次的主要边切断 则第二步只有一种选择切附加边 ans+=1
- 第一步把覆盖2次或以上的主要边切断 则不可能击败Dark
这样我们就可以统计出ans
解决每条边的覆盖次数 需要用到树上差分算法
我们给每个节点初值为0
对于每条附加边(x,y) 我们给x和y节点权值+1
对于x和y的lca节点权值-2(想想为什么)
设F(x)为以x为根的子树中各节点的权值和 则F(x)就是x与其父节点之间树边被覆盖的次数
最后统计ans即可
PS:这题需要把cin cout 改为scanf printf 不然会TLE 坑了我一晚上
代码
#include<iostream>
#include<cstdio>
#include<cmath>
using namespace std;
#define maxn 100010
int n,m,cnt,ans;
int h[maxn],dep[maxn],f[maxn][],vis[maxn];
struct Edge
{
int next;
int to;
}e[maxn<<];
void add(int u,int v)
{
e[++cnt].to=v;
e[cnt].next=h[u];
h[u]=cnt;
}
void deal(int u,int fa)
{
dep[u]=dep[fa]+;//深度等于父节点+1
for(int i=;i<=;i++)//枚举倍增步数
{
f[u][i]=f[f[u][i-]][i-];//二分思想
}
for(int i=h[u];i;i=e[i].next)
{
int v=e[i].to;
if(v==fa) continue;//如果是父节点跳过
f[v][]=u;//如果是子节点
deal(v,u);
}
}
int lca(int x,int y)
{
if(dep[x]<dep[y]) swap(x,y);//保证x的深度大
for(int i=;i>=;i--)//从大开始枚举
{
if(dep[f[x][i]]>=dep[y]) x=f[x][i];//先跳到同一层
if(x==y) return x;//如果已经找到
}
for(int i=;i>=;i--)//此时x y已经在同一层
{
if(f[x][i]!=f[y][i])//如果不同就继续跳
{
x=f[x][i];
y=f[y][i];
}
}
return f[x][];
}
void dp(int x)
{
for(int i=h[x];i;i=e[i].next)
{
int v=e[i].to;
if(v==f[x][]) continue;
dp(v);//不是父亲时 继续找
vis[x]+=vis[v];//递归回来时加上所有节点的权值
}
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=;i<n;i++)
{
int a,b;
scanf("%d%d",&a,&b);
add(a,b);//无向图
add(b,a);
}
deal(,);//预处理
for(int i=;i<=m;i++)
{
int a,b;
scanf("%d%d",&a,&b);
vis[a]++;//树上差分算法
vis[b]++;
vis[lca(a,b)]-=;
}
dp();//计算所有主要边被覆盖几次
for(int i=;i<=n;i++)//从2开始是因为我们把点存成边
{
if(vis[i]==)//被覆盖0次
ans+=m;
if(vis[i]==)//被覆盖1次
ans++;
}
printf("%d",ans);
}
【题解】POJ 3417 Network(倍增求LCA+DP+树上差分)的更多相关文章
- poj 3417 Network(tarjan lca)
poj 3417 Network(tarjan lca) 先给出一棵无根树,然后下面再给出m条边,把这m条边连上,然后每次你能毁掉两条边,规定一条是树边,一条是新边,问有多少种方案能使树断裂. 我们设 ...
- poj 3417 Network 题解
题意: 先给出一棵树,然后再给出m条边,把这m条边连上,然后剪掉两条边,一条是原边,一条是新边,问有多少种方案能使图不连通. 思路: 从原边的角度看 1.树加边,一定成环,加一条(u,v)边就有u-& ...
- 【题解】洛谷P4180 [BJWC2010] 严格次小生成树(最小生成树+倍增求LCA)
洛谷P4180:https://www.luogu.org/problemnew/show/P4180 前言 这可以说是本蒟蒻打过最长的代码了 思路 先求出此图中的最小生成树 权值为tot 我们称这棵 ...
- 【倍增】洛谷P3379 倍增求LCA
题目描述 如题,给定一棵有根多叉树,请求出指定两个点直接最近的公共祖先. 输入输出格式 输入格式: 第一行包含三个正整数N.M.S,分别表示树的结点个数.询问的个数和树根结点的序号. 接下来N-1行每 ...
- 树上倍增求LCA(最近公共祖先)
前几天做faebdc学长出的模拟题,第三题最后要倍增来优化,在学长的讲解下,尝试的学习和编了一下倍增求LCA(我能说我其他方法也大会吗?..) 倍增求LCA: father[i][j]表示节点i往上跳 ...
- [算法]树上倍增求LCA
LCA指的是最近公共祖先(Least Common Ancestors),如下图所示: 4和5的LCA就是2 那怎么求呢?最粗暴的方法就是先dfs一次,处理出每个点的深度 然后把深度更深的那一个点(4 ...
- hdu 2586 How far away ? 倍增求LCA
倍增求LCA LCA函数返回(u,v)两点的最近公共祖先 #include <bits/stdc++.h> using namespace std; *; struct node { in ...
- 倍增求lca模板
倍增求lca模板 https://www.luogu.org/problem/show?pid=3379 #include<cstdio> #include<iostream> ...
- 倍增求LCA学习笔记(洛谷 P3379 【模板】最近公共祖先(LCA))
倍增求\(LCA\) 倍增基础 从字面意思理解,倍增就是"成倍增长". 一般地,此处的增长并非线性地翻倍,而是在预处理时处理长度为\(2^n(n\in \mathbb{N}^+)\ ...
随机推荐
- Javascript之for循环该注意的问题
很多时候我们都用到for循环,而用到for循环部门往往对一个数组进行循环,其中我们很多时候都是这样写的: // 次佳的循环 for (var i = 0; i < myarray.length; ...
- docker 镜像构建上下文理解
原文 写得贼好,特别鸣谢,哈哈 如果注意,会看到 docker build 命令最后有一个 . . . 表示当前目录,而 Dockerfile就在当前目录,因此不少初学者以为这个路径是在指定 Dock ...
- div的隐藏占用空间位置关系
display:none和visibility:hidden都是把网页上某个元素隐藏起来的功能,但两者有所区别,经过亲自实验,我发现使用 visibility:hidden属性会使对象不可见,但该对象 ...
- JavaScript里面的居民们1-数据
编码 首先练习数字相关的一些操作: <div> <label>Number A:<input id="radio-a" type="radi ...
- git 批量删除 tag
1. master分支存在大量冗余tag aa0e24dfd920a85c39da400a404309cb6fc69dc0 refs/tags/rc_69 f36f3f21f1ce61db3974e9 ...
- FastJson 常见问题
一.场景 在使用序列化的时候,Object里包含了两个一模一样的对象,所以解析的时候,只有第一个能解析出来,另外一个无法显示. 查看了json的序列化源码,发现是DisableCircularRefe ...
- 核心API
1.ProcessEngine ProcessEngine是Activiti中最核心的类,其他的类都是由他而来.Activiti流程引擎的配置文件是名为 activiti.cfg.xml 的XML文件 ...
- Java中生成帮助文档
如何在Java中使用注释 在编写程序时,经常需要添加一些注释,用以描述某段代码的作用. 一般来说,对于一份规范的程序源代码而言,注释应该占到源代码的 1/3 以上.因此,注释是程序源代码的重要组成部分 ...
- GitHub教程(一) 使用指南
刚进公司上班的时候,技术总监让我熟悉一下Git(分布式版本控制工具)操作命令和GitHub(代码托管平台),说实话之前我也没有具体使用过Git工具,但是GitHub我还是注册过账号的.在练习将本地仓库 ...
- SQL Server ->> Sparse File(稀疏文件)
Sparse File(稀疏文件)不是SQL Server的特性.它属于Windows的NTFS文件系统的一个特性.如果某个大文件中的数据包含着大量“0数据”(这个应该从二进制上看),这样的文件就可以 ...