题意:给定一棵n个节点的树,然后在给定m条边,去掉m条边中的一条和原树中的一条边,使得树至少分为两部分,问有多少种方案。

神题,一点也想不到做法,

首先要分析出加入一条边之后会形成环,形成环的话,如果去掉该边和环上面没有被其他环覆盖的边,那么便分为两部分了。

这样只需要记录每条边被环覆盖了几次即可,

用dp[u]表示u点的父边被覆盖了几次。

每次新加进来一条边(a,b) dp[a] ++ ,dp[b] ++ , dp[lca(a,b)] -= 2;

所有边处理完之后,遍历一边此树,同时转移状态 dp[u] += dp[v];

#define maxn 100005

struct node
{
int v,next;
};
node e[maxn * ];
int cnt ;
int head[maxn * ];
int num ;
int E[maxn * + ],L[maxn * + ],R[maxn * + ];
int f[maxn * + ][];
int dp[maxn];
void init()
{
cnt = ;
memset(head,-,sizeof(head));
}
void add(int u ,int v)
{
e[cnt].v = v ;
e[cnt].next = head[u];
head[u] = cnt ++ ;
e[cnt].v = u;
e[cnt].next = head[v] ;
head[v] = cnt ++ ;
return ;
}
void dfs(int u ,int fa,int dep)
{
E[++num] = u , L[num] = dep , R[u] = num;
for(int i = head[u] ;i != -; i = e[i].next)
if(e[i].v != fa)
{
int v = e[i].v;
dfs(v, u, dep + );
E[++num] = u , L[num] = dep;
}
return;
}
void initRMQ()
{
for(int i = ; i <= num ;i ++ ) f[i][] = i;
for(int j = ; (<<j) <= num ; j++ )
for(int i = ; i + (<<j) - <= num; i ++ )
if(L[f[i][j-]] < L[f[i+(<<(j-))][j-]]) //ps:注意下标
f[i][j] = f[i][j-];
else f[i][j] = f[i+(<<(j-))][j-];
}
int lca(int a ,int b)
{
a = R[a] , b = R[b];
if(a>b) swap(a,b);
int k = (log(1.0 + b - a )/log(2.0));
if(L[f[a][k]] < L[f[b-(<<k)+][k]] )
return E[f[a][k]];
else return E[f[b-(<<k)+][k]];
}
void dfs(int u,int fa)
{
for(int i = head[u] ; i != - ; i =e[i].next)
if(e[i].v != fa)
{
int v = e[i].v;
dfs(v,u);
dp[u] += dp[v];
}
return ;
}
int main()
{
int n,m;
int u,v;
while(scanf("%d%d",&n,&m)!=EOF)
{
init();
for(int i = ; i < n - ; i ++ )
{
scanf("%d%d",&u,&v);
add(u,v);
}
num = ;
memset(R,,sizeof(R));
dfs(,,);
initRMQ();
memset(dp,,sizeof(dp));
for(int i = ; i < m ; i ++ )
{
scanf("%d%d",&u,&v);
dp[u] ++ ;
dp[v] ++ ;
dp[lca(u,v)] -= ;
}
dfs(,);
int sum ;
sum = ;
for(int i = ;i <= n ; i++ ) // ps:1为根不要选。
{
if(dp[i] == )
sum ++;
else if(dp[i] == )
sum += m;
}
printf("%d\n",sum);
}
return ;
} /*
好题:
离线LCA + 树形DP 分析:加进来一条边(a,b),会形成一条环 a - lca(a,b) - b
如果去掉(a,b)和没有被其他环覆盖的边,那么就能把树分成两部分。
只要记录dp[u]表示u的负边被环覆盖了几次
对于新加进来的一条边(a,b) dp[a] ++ , dp[b] ++ , dp[lca(a,b)] -= 2;///
这样处理为完所有新加进来的边之后,在dfs一边,跑完状态转移:dp[u] += dp[v];
这里就可以把每条环上的边都依次加1,并且因为lca(a,b)的父边不再环上,且已经提前减去了2
这样转移正好可以把减掉的2消去。 注意:这里把lca离线处理成rmq,只需要O(n)的遍历和O(nlogn)的预处理即可。 ST表 并且这里以1为根,后面的状态转移也要以1为根,否则lca就白算了。 */

poj3417

poj3417 Network 树形Dp+LCA的更多相关文章

  1. SGU 149. Computer Network( 树形dp )

    题目大意:给N个点,求每个点的与其他点距离最大值 很经典的树形dp...很久前就想写来着...看了陈老师的code才会的...mx[x][0], mx[x][1]分别表示x点子树里最长的2个距离, d ...

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

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

  3. Uva LA 3902 - Network 树形DP 难度: 0

    题目 https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&page=show_pr ...

  4. poj 3417 树形dp+LCA

    思路:我以前一直喜欢用根号n分段的LCA.在这题上挂了,第一次发现这样的LCA被卡.果断改用Tarjan离线算法求LCA. 当前节点为u,其子节点为v.那么: 当以v根的子树中含有连接子树以外点的边数 ...

  5. poj3417 Network 树上差分+LCA

    题目传送门 题目大意:给出一棵树,再给出m条非树边,先割掉一条树边,再割掉一条非树边,问有几种割法,使图变成两部分. 思路:每一条 非树边会和一部分的树边形成一个环,分三种情况: 对于那些没有形成环的 ...

  6. POJ 3728 The merchant (树形DP+LCA)

    题目:https://vjudge.net/contest/323605#problem/E 题意:一棵n个点的树,然后有m个查询,每次查询找(u->v)路径上的两个数,a[i],a[j],(i ...

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

    Famil Door's City map looks like a tree (undirected connected acyclic graph) so other people call it ...

  8. HDU4008 Parent and son(树形DP LCA)

    先记录以1为根时每个节点子树儿子节点的最大与次小值,询问x, y时,先判断x在不在y的子树范围内,若不在,结果为y的儿子结点,后继的最小值. 若x在y的子树范围内,若y儿子最小值是x的前驱,从次小值与 ...

  9. poj3417 LCA + 树形dp

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

随机推荐

  1. JAVA程序生成XML标准化的文件格式,缩进,美化。

    //他开始Document映射到文件 TransformerFactory transFactory = TransformerFactory.newInstance(); Transformer t ...

  2. BST树,B树、B-树、B+树、B*树

    BST树,B树.B-树.B+树.B*树 二叉搜索树(BST): 1.所有非叶子结点至多拥有两个儿子(Left和Right): 2.所有结点存储一个关键字: 3.非叶子结点的左指针指向小于其关键字的子树 ...

  3. mediator pattern

    20.4 中介者模式总结 中介者模式将一个网状的系统结构变成一个以中介者对象为中心的星形结构,在这个星型结构中,使用中介者对象与其他对象的一对多关系来取代原有对象之间的多对多关系.中介者模式在事件驱动 ...

  4. VS2012 编译程序时报无法载入PDB文件错误解决方式

    VS2012 编译程序时报无法载入PDB文件错误解决方式 "ConsoleApplication1.exe"(Win32): 已载入"C:\Users\hp\Docume ...

  5. python udp编程实例

    与python tcp编程控制见 http://blog.csdn.net/aspnet_lyc/article/details/39854569 c++ udp/tcp 编程见 http://blo ...

  6. BZOJ 2007 NOI2010 海拔高度 最小减产计划

    标题效果:YT城市是一个精心规划的城市.这个城市是东西向和南北向干道成n×n地区性.简单.可以YT作为一个城市广场,每个区域也可被视为一个正方形.因此,.YT市中含有(n+1)×(n+1)交叉口和2n ...

  7. dev layoutControl 控件使用

    对于排版控件,用微软的方法都是先拉 label再拉一个 Textbox  ,  虽然微软的控件了有类似于 EXCEL的单元格全并功能,但用起来使终不方便, 今天研究了一下 DEV 的这个控件,比微软的 ...

  8. 【C语言探索之旅】 第一部分第八课:第一个C语言小游戏

    ​ 内容简介 1.课程大纲 2.第一部分第八课:第一个C语言小游戏 3.第一部分第九课预告: 函数 课程大纲 我们的课程分为四大部分,每一个部分结束后都会有练习题,并会公布答案.还会带大家用C语言编写 ...

  9. 开源Math.NET基础数学类库使用(01)综合介绍

    原文:[原创]开源Math.NET基础数学类库使用(01)综合介绍 开源Math.NET基础数学类库使用系列文章总目录:   1.开源.NET基础数学计算组件Math.NET(一)综合介绍    2. ...

  10. Jafka来源分析——Processor

    Jafka Acceptor接受client而建立后的连接请求,Acceptor会将Socket连接交给Processor进行处理.Processor通过下面的处理步骤进行client请求的处理: 1 ...