先给个LCA模板

HDU 1330(LCA模板)

#include <cstdio>
#include <cstring>
#define N 40005
struct Edge{
int x,y,d,ne;
};
Edge e[N*],e2[N*];
int be[N],be2[N],all,all2,n,m;
bool vis[N];
int fa[N];
int ancestor[N][];
int dis[N]; void add(int x, int y, int d, Edge e[], int be[], int &all)
{
e[all].y=y;e[all].x=x;e[all].d=d;
e[all].ne=be[x];
be[x]=all++; e[all].y=x;e[all].x=y;e[all].d=d;
e[all].ne=be[y];
be[y]=all++;
} void init()
{
all=all2=;
memset(be,-,sizeof(be));
memset(be2,-,sizeof(be2));
memset(vis,,sizeof(vis));
for(int i=; i<=n; i++)
fa[i]=i;
} int find(int x)
{
if(fa[x]!=x) fa[x]=find(fa[x]);
return fa[x];
} void tarjan(int u)
{
vis[u]=;
for(int i=be2[u]; i!=-; i=e2[i].ne)
if(vis[e2[i].y])
ancestor[e2[i].d][]=find(e2[i].y); for(int i=be[u]; i!=-; i=e[i].ne)
if(!vis[e[i].y])
{
dis[e[i].y]=dis[u]+e[i].d;
tarjan(e[i].y);
fa[e[i].y]=u;
}
} int main()
{
int tt;
scanf("%d",&tt);
while(tt--)
{
int x,y,d;
scanf("%d%d",&n,&m);
init();
for(int i=; i<n-; i++)
{
scanf("%d%d%d",&x,&y,&d);
add(x,y,d,e,be,all);
}
for(int i=; i<m; i++)
{
scanf("%d%d",&x,&y);
add(x,y,i,e2,be2,all2);
ancestor[i][]=x;
ancestor[i][]=y;
}
dis[]=;
tarjan();//从根节点开始
for(int i=; i<m; i++)
printf("%d\n",dis[ancestor[i][]]+dis[ancestor[i][]]-*dis[ancestor[i][]]);
}
return ;
}

HDU 4912

Paths on the tree

Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)
Total Submission(s): 428    Accepted Submission(s): 128

Problem Description
bobo has a tree, whose vertices are conveniently labeled by 1,2,…,n.

There are m paths on the tree. bobo would like to pick some paths while any two paths do not share common vertices.

Find the maximum number of paths bobo can pick.

 
Input
The input consists of several tests. For each tests:

The first line contains n,m (1≤n,m≤105). Each of the following (n - 1) lines contain 2 integers ai,bi denoting an edge between vertices ai and bi (1≤ai,bi≤n). Each of the following m lines contain 2 integers ui,vi denoting a path between vertices ui and vi (1≤ui,vi≤n).

 
Output
For each tests:

A single integer, the maximum number of paths.

 
Sample Input
3 2
1 2
1 3
1 2
1 3
7 3
1 2
1 3
2 4
2 5
3 6
3 7
2 3
4 5
6 7
 
Sample Output
1
2
 

贪心法,找出给定路径左右节点的最近公共祖先,按其最近公共祖先的深度从大到小插入,每次插入将其子树标记,之后若路径节点若已访问则判不可行,否则ans+1

#include <iostream>
#include <cstring>
#include <cstdio>
#include <vector>
#define max(x,y) ((x)>(y)?(x):(y))
#define NN 200002 // number of house
using namespace std; int be[NN],all,ans;
bool vis2[NN],vis3[NN]; typedef struct node{
int v;
int d;
struct node *nxt;
}NODE; struct edge{
int u,v,ne;
}e[NN]; NODE *Link1[NN];
NODE edg1[NN * ]; NODE *Link2[NN];
NODE edg2[NN * ]; int idx1, idx2, N, M;
int res[NN][];
int fat[NN];
int vis[NN];
int dis[NN]; void Add(int u, int v, int d, NODE edg[], NODE *Link[], int &idx){
edg[idx].v = v;
edg[idx].d = d;
edg[idx].nxt = Link[u];
Link[u] = edg + idx++; edg[idx].v = u;
edg[idx].d = d;
edg[idx].nxt = Link[v];
Link[v] = edg + idx++;
} int find(int x){
if(x != fat[x]){
return fat[x] = find(fat[x]);
}
return x;
} void Tarjan(int u){
vis[u] = ;
fat[u] = u; for (NODE *p = Link2[u]; p; p = p->nxt){
if(vis[p->v]){
res[p->d][] = find(p->v);
}
} for (NODE *p = Link1[u]; p; p = p->nxt){
if(!vis[p->v]){
dis[p->v] = dis[u] + p->d;
Tarjan(p->v);
fat[p->v] = u;
}
}
} void add(int fa,int x,int y)
{
++all;
e[all].u=x;
e[all].v=y;
e[all].ne=be[fa];
be[fa]=all;
} void color(int u)
{
for (NODE *p = Link1[u]; p; p = p->nxt)
if(vis3[p->v] && !vis2[p->v])
{
vis2[p->v]=;
color(p->v);
}
} void dfs(int u)
{
vis[u]=;
for (NODE *p = Link1[u]; p; p = p->nxt)
if(!vis[p->v]) dfs(p->v); for (int i=be[u]; i!=-; i=e[i].ne)
if(!vis2[e[i].u] && !vis2[e[i].v])
{
vis2[u]=;
ans++;
color(u);
}
vis3[u]=; } int main() {
int T, i, u, v, d;
while(scanf("%d%d", &N, &M)!=EOF)
{
idx1 = ;
memset(Link1, , sizeof(Link1));
for (i = ; i < N; i++){
scanf("%d%d", &u, &v);
d=;
Add(u, v, d, edg1, Link1, idx1);
} idx2 = ;
memset(Link2, , sizeof(Link2));
for (i = ; i <= M; i++){
scanf("%d%d", &u, &v);
Add(u, v, i, edg2, Link2, idx2);
res[i][] = u;
res[i][] = v;
} memset(vis, , sizeof(vis));
dis[] = ;
Tarjan(); all=;
memset(be,-,sizeof(be));
memset(vis,,sizeof(vis));
memset(vis2,,sizeof(vis2));
memset(vis3,,sizeof(vis3));
for(int i=;i<=M; i++)
add(res[i][],res[i][],res[i][]);
for(int i=; i<=N; i++)
fat[i]=i;
ans=;
dfs();
printf("%d\n",ans);
}
return ;
}

HDU 2586 + HDU 4912 最近公共祖先的更多相关文章

  1. LCA(最近公共祖先)--tarjan离线算法 hdu 2586

    HDU 2586 How far away ? Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/ ...

  2. hdu 2586(最近公共祖先LCA)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2586 思路:在求解最近公共祖先的问题上,用到的是Tarjan的思想,从根结点开始形成一棵深搜树,非常好 ...

  3. HDU 2586 How far away ?(LCA模板 近期公共祖先啊)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2586 Problem Description There are n houses in the vi ...

  4. LCA最近公共祖先-- HDU 2586

    题目链接 Problem Description There are n houses in the village and some bidirectional roads connecting t ...

  5. hdu - 2586 How far away ?(最短路共同祖先问题)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2586 最近公共祖先问题~~LAC离散算法 题目大意:一个村子里有n个房子,这n个房子用n-1条路连接起 ...

  6. HDU 4547 CD操作 (LCA最近公共祖先Tarjan模版)

    CD操作 倍增法  https://i.cnblogs.com/EditPosts.aspx?postid=8605845 Time Limit : 10000/5000ms (Java/Other) ...

  7. HDU 2586 (LCA模板题)

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=2586 题目大意:在一个无向树上,求一条链权和. 解题思路: 0 | 1 /   \ 2      3 ...

  8. HDU - 2586 How far away ?(LCA模板题)

    HDU - 2586 How far away ? Time Limit: 1000MS   Memory Limit: 32768KB   64bit IO Format: %I64d & ...

  9. HDU 2586 How far away ?【LCA】

    任意门:http://acm.hdu.edu.cn/showproblem.php?pid=2586 How far away ? Time Limit: 2000/1000 MS (Java/Oth ...

随机推荐

  1. 计划:怎样理解水平集方法 ITK Level set V4 框架介绍

    简易解释:在曲面中插入一个平面所形成的轮廓,即是该轮廓的水平集表示,可见,该轮廓的水平集表示有多个.对于图像分割,在图像力的驱动下曲面进行更新. 轮廓的数学表达有隐式和显式两种表达.用曲面演化代替Fr ...

  2. vs2008调试提示:未安装Silverlight托管调试包

    换个启动浏览器,解决了. 右击项目,选择“属性”,选择"web";启动操作设置“启动外部程序”,填入浏览器exe的路径. 命令行参数填入地址.即可.

  3. BZOJ 3436: 小K的农场 差分约束

    题目链接: http://www.lydsy.com/JudgeOnline/problem.php?id=3436 题解: 裸的差分约束: 1.a>=b+c  ->  b<=a-c ...

  4. jquery中的事件

    一.事件参数   function(event){} 1.停止冒泡事件  event.stopPropagation()  <=>  return false;2.阻止默认行为  even ...

  5. 单例模式(.NET)

    问题描述:         单例模式 Singleton Pattern 问题解决: (1)单例模式简介: Singleton模式要求一个类有且仅有一个实例,并且提供了一个全局的访问点.这就提出了一个 ...

  6. 剑指offer--面试题16

    #include<stack> //思路:遍历链表过程中,将各个指针入栈,再出栈进行反转 ListNode* ReverseList(ListNode* pHead) { if(pHead ...

  7. C#枚举注释实例

    public enum 枚举名称    {        /// <summary>        /// 注释描述1        /// </summary>        ...

  8. VisionTimer BUG && Start

    void Start() { vp_Timer.In(0.0f, delegate() { Debug.Log("Start"); }, 10, 1.0f); } Version ...

  9. Unity GameObject.activeSelf, GameObject.activeInHierarchy,GameObject.SetActive和SetActiveRecursively

    activeSelf(read only只读):物体本身的active状态,对应于其在inspector中的checkbox是否被勾选activeInHierarchy(read only只读):物体 ...

  10. 【面试题004】c/c++字符串,替换空格

      一,c/c++字符串 1.C/C++中每个字符串都以字符’\0‘作为结尾,这样我们就能很方便地找到字符串的最后尾部. 由于这个原因每个字符串都有一个额外的开销,注意字符串越界的问题: 2.C/C+ ...