题意:给出一棵无根树,然后下面再给出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. WPF之DataTemplateSelector技巧

    WPF中如何通过一个属性来控制对象的模板,属性值改变时对象的模板会跟随改变? 两个关键点   1 属性/对象更改通知 方法一:继承INotifyPropertyChanged接口,当属性值更改时需要让 ...

  2. C++复习:位运算

    与          a&b :    1010&1100=1000  或          a|b  :  1010|1100=1110 异或       a^b :     101 ...

  3. iOS中对于多个按钮,选中其中一个,其他按钮选中状态为NO

      第一,定义一个全局的按钮变量 /** *  按钮选中,中间值 */ @property (nonatomic,strong) UIButton *selectedBtn; 第二,添加多个按钮到sc ...

  4. KVC基本使用

    首先,创建两个类.person类和book类.如图: watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/ ...

  5. C#多线程学习(六) 互斥对象

    如何控制好多个线程相互之间的联系,不产生冲突和重复,这需要用到互斥对象,即:System.Threading 命名空间中的 Mutex 类. 我们可以把Mutex看作一个出租车,乘客看作线程.乘客首先 ...

  6. python 基础 2.8 python练习题

    python 练习题:   #/usr/bin/python #coding=utf-8 #@Time   :2017/10/26 9:38 #@Auther :liuzhenchuan #@File ...

  7. idea创建普通java项目以及maven创建项目过程(转)

    1. idea创建一个普通项目流程 http://blog.csdn.net/testcs_dn/article/details/52303941 2. idea创建maven项目流程 http:// ...

  8. 7 Types of Regression Techniques

    https://www.analyticsvidhya.com/blog/2015/08/comprehensive-guide-regression/ What is Regression Anal ...

  9. SAP-Function_01

    TH_POPUP –在特定用户屏幕上显示一个系统消息 1 . 函数WS_UPLOAD     功能﹕将TXT文件转换成SAP中的内表定义的数据表格文件    注意﹕1 函数将按参数 data_tab  ...

  10. C++三种继承方式

    一.三种继承方式 继承方式不同,第一个不同是的是派生类继承基类后,各成员属性发生变化.第二个不同是派生类的对象能访问基类中哪些成员发生变化.表格中红色标注.