题意:给出一棵无根树,然后下面再给出m条边,把这m条边连上,每次你去两条边,规定一条是树边,一条是新边,问有多少种方案能使树断裂。

解题关键:边权转化为点权,记录每条边被环覆盖的次数,通过val[a]++,val[b]++,val[lca(a,b)]-=2,来控制每个点上面的边,所以树的顶点要去掉。

好久没1A了,开心

 //#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cstdlib>
#include<cmath>
#include<iostream>
#include<vector>
typedef long long ll;
using namespace std;
const int maxn=;
const int maxm=;
int _pow[maxm],m,n;
int head[maxn],tot;
int ver[maxn*],depth[maxn*],first[maxn],rmq[maxn*][],id;//5个数组,注意哪个需要乘2
int pre[maxn],val[maxn];
int ans;
inline int read(){
char k=;char ls;ls=getchar();for(;ls<''||ls>'';k=ls,ls=getchar());
int x=;for(;ls>=''&&ls<='';ls=getchar())x=(x<<)+(x<<)+ls-'';
if(k=='-')x=-x;return x;
} struct edge{
int to,nxt;
}e[maxn*];//链式前向星建树 void init(){
memset(head,-,sizeof head);
tot=;
id=;
ans=;
} void add_edge(int u,int v){
e[tot].to=v;
e[tot].nxt=head[u];
head[u]=tot++;
} void dfs(int u,int fa,int dep){
ver[++id]=u;//第i个访问到的结点编号
depth[id]=dep;//第i个访问到的结点深度
first[u]=id;
for(int i=head[u];i!=-;i=e[i].nxt){
int v=e[i].to;
if(v==fa) continue;
//pre[v]=u;
dfs(v,u,dep+);
ver[++id]=u;//后序遍历,再次访问父节点
depth[id]=dep;
}
} void rmq_init(int n){
int k=int(log(n)/log());
for(int i=;i<=n;++i) rmq[i][]=i;
for(int j=;j<=k;++j){
for(int i=;i+_pow[j]-<=n;++i){//因为存的是索引
int a=rmq[i][j-],b=rmq[i+_pow[j-]][j-];
rmq[i][j]=depth[a]<depth[b]?a:b;
}
}
} int rmq_query(int l,int r){
int k=int(log(r-l+1.0)/log(2.0));
int a=rmq[l][k],b=rmq[r-_pow[k]+][k];
return depth[a]<depth[b]?a:b;
}//返回的依然是索引 int LCA(int u,int v){
int x=first[u],y=first[v];
if(x>y)swap(x,y);
int res=rmq_query(x,y);
return ver[res];
}
void dfs(int u,int fa){
for(int i=head[u];i!=-;i=e[i].nxt){
int v=e[i].to;
if(v==fa) continue;
dfs(v,u);
val[u]+=val[v];
}
if(val[u]==) ans++;
else if(!val[u]&&u!=) ans+=m;
} int main(){
for(int i=;i<maxm;++i) _pow[i]=<<i; //预处理2^n
int k,a,b;
n=read();m=read();
init();
//for(int i=1;i<=n;i++) val[i]=read();
for(int i=;i<n-;++i){
a=read(),b=read();
add_edge(a,b);
add_edge(b,a);
}
dfs(,-,);
rmq_init(*n-);
for(int i=;i<m;++i){
a=read();b=read();
val[a]++,val[b]++,val[LCA(a,b)]-=;
}
dfs(,-);
printf("%d\n",ans); return ;
}

[poj3417]Network(LCA+树形dp)的更多相关文章

  1. poj3417 LCA + 树形dp

    Network Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 4478   Accepted: 1292 Descripti ...

  2. Codeforces Round #343 (Div. 2) E. Famil Door and Roads lca 树形dp

    E. Famil Door and Roads 题目连接: http://www.codeforces.com/contest/629/problem/E Description Famil Door ...

  3. HDU 4008 Parent and son LCA+树形dp

    题意: 给定case数 给定n个点的树,m个询问 以下n-1行给出树边 m个询问 x y 问:以x为根.y子树下 y的最小点标的儿子节点 和子孙节点 思路: 用son[u][0] 表示u的最小儿子 s ...

  4. poj3417 Network——LCA+树上差分

    题目:http://poj.org/problem?id=3417 根据一条边被几个环覆盖来判断能不能删.有几种情况等: 用树上差分,终点 s++,LCA s-=2,统计时计算子树s值的和即可: 用S ...

  5. 可恶!学了这么久的LCA,联考的题目却是LCA+树形DP!!!可恶|!!!这几天想学学树形DP吧!先来一道入门题HDU 1520 Anniversary party

    题目描述 某大学有N个职员,编号为1~N.他们之间有从属关系,也就是说他们的关系就像一棵以校长为根的树,父结点就是子结点的直接上司.现在有个周年庆宴会,宴会每邀请来一个职员都会增加一定的快乐指数Ri, ...

  6. poj3417 Network 树形Dp+LCA

    题意:给定一棵n个节点的树,然后在给定m条边,去掉m条边中的一条和原树中的一条边,使得树至少分为两部分,问有多少种方案. 神题,一点也想不到做法, 首先要分析出加入一条边之后会形成环,形成环的话,如果 ...

  7. hdu_5293_Tree chain problem(DFS序+树形DP+LCA)

    题目连接:http://acm.hdu.edu.cn/showproblem.php?pid=5293 被这题打蹦了,看着题解写的,很是爆炸,确实想不到,我用的DFS序+LCA+树形DP,当然也可以写 ...

  8. 【BZOJ-3631】松鼠的新家 树形DP?+ 倍增LCA + 打标记

    3631: [JLOI2014]松鼠的新家 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 1231  Solved: 620[Submit][Stat ...

  9. Codeforces 418d Big Problems for Organizers [树形dp][倍增lca]

    题意: 给你一棵有n个节点的树,树的边权都是1. 有m次询问,每次询问输出树上所有节点离其较近结点距离的最大值. 思路: 1.首先是按照常规树形dp的思路维护一个子树节点中距离该点的最大值son_di ...

随机推荐

  1. EF Core 日志跟踪sql语句

    EF Core 日志跟踪sql语句 官方文档链接:https://docs.microsoft.com/en-us/ef/core/miscellaneous/logging 1.新增自定义ILogg ...

  2. Executors几种常用的线程池性能比较

    java编程中,经常会利用Executors的newXXXThreasPool生成各种线程池,今天写了一小段代码,简单测试了下三种常用的线程池: import com.google.common.ut ...

  3. Javascript文件加载:LABjs和RequireJS

    传统上,加载Javascript文件都是使用<script>标签. 就像下面这样: <script type="text/javascript" src=&quo ...

  4. Project Euler:Problem 41 Pandigital prime

    We shall say that an n-digit number is pandigital if it makes use of all the digits 1 to n exactly o ...

  5. mysql的分库分表

    1 什么是分库分表 这里讨论的情况是一台机器上对应一个数据库. 分库的对象是表,分表的对象是行.分库是说把属于同一个模块的相关性很高的表放在同一个数据库中.分表是说把同一个表的的行分成多个子表,把各个 ...

  6. xutils3基本使用

    根目录下新建一个类继承application,调用xUtils3初始化方法 public class AtguiguApplication extends Application { @Overrid ...

  7. gradle 添加依赖

    files 添加libs下的 project 添加一个module compile 去下载一个

  8. Android Weekly Notes Issue #261

    Android Weekly Issue #261 June 11th, 2017 Android Weekly Issue #261 本期内容包括: Adaptive Icons; Kotlin实现 ...

  9. 20145239杜文超 《Java程序设计》第10周学习总结

    20145239 <Java程序设计>第10周学习总结 教材学习内容总结 Java的网络编程 网络编程 网络编程就是在两个或两个以上的设备(例如计算机)之间传输数据. 网络概述 1.计算机 ...

  10. Appium——api常用函数

    appium常用函数介绍:   获取页面信息:   1. def get_current_activity(cls, driver): ''' 获取当前页面的activity :param drive ...