先给个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. MySQL中的配置参数interactive_timeout和wait_timeout(可能导致过多sleep进程的两个参数)

    1)interactive_timeout:参数含义:服务器关闭交互式连接前等待活动的秒数.交互式客户端定义为在mysql_real_connect()中使用CLIENT_INTERACTIVE选项的 ...

  2. matlab查找回车字符

    Hi all, I would like to read the data all at once with: `file_text = fread(fid, inf, 'uint8=>char ...

  3. Document Set 【一】

    概括介绍: Document Set 是SharePoint2010之后出现的一个新的Feature.这个Feature的主要目的是两个: 1,是帮助 User 以一个文件的管理方式管理一个文件集合. ...

  4. sqlserver 获取时间年月日时分秒

    转自:http://blog.itpub.net/14766526/viewspace-1156100/ select GETDATE() as '当前日期',DateName(year,GetDat ...

  5. 输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历的结果。如果是则输出Yes,否则输出No。假设输入的数组的任意两个数字都互不相同。

    // ConsoleApplication2.cpp : 定义控制台应用程序的入口点. // #include "stdafx.h" #include "stdafx.h ...

  6. 初尝backbone

    backbone的基础知识在此将不再进行介绍.自己后续应该会整理出来,不过今天先把这几天学的成果用一个demo进行展示. 后续可运行demo将会在sinaapp上分享,不过近期在整理sinaapp上d ...

  7. C# textbox 滚动条 随文本输入 滚动

    tb_Log.SelectionStart = tb_Log.Text.Length;//设置光标位置 tb_Log.ScrollToCaret();//随文本输入 滚动

  8. [转载]C#获取进程的主窗口句柄

    public class User32API { private static Hashtable processWnd = null; public delegate bool WNDENUMPRO ...

  9. MoveManager管理类

    MoveManager:移动管理类 struct MoveOpt { int cur_seq; ObjecInfo* obj; }; std::map<ObjID, MoveOpt> m_ ...

  10. C# MessageBox 用法大全(转)

    C# MessageBox 用法大全 http://www.cnblogs.com/Tammie/archive/2011/08/05/2128623.html 我们在程序中经常会用到MessageB ...