HDU 4912 LCA+贪心

Paths on the tree

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

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

题目意思:
给出一棵树,总共n个结点n-1条边,然后给出m个条路径的两端结点的编号,求m条路径互相不相交的最大个数为多少。

思路:

求出每个路径两端端点的最近公共结点,然后把lca按照深度从大到小排序,然后开始贪心,每次若这条路径上的点没有被visited过,那么ans++,然后把这条路径上所有点visited。最终结果即为ans。

代码:

  1 #include <cstdio>
  2 #include <cstring>
  3 #include <algorithm>
  4 #include <vector>
  5 #include <queue>
  6 #include <iostream>
  7 using namespace std;
  8 #define N 100005
  9 #define M 20
 10
 11 int n, m;
 12
 13 struct Edge{
 14     int u, v, f, w;
 15     Edge(int a=0,int b=0,int c=0,int d=0):u(a),v(b),f(c),w(d){}
 16 }e[N];
 17
 18 int dep[N];
 19 int f[N][M];
 20 int visited[N];
 21 vector<int>ve[N];
 22
 23 void init(){
 24     memset(dep,0,sizeof(dep));
 25     memset(f,0,sizeof(f));
 26     memset(visited,0,sizeof(visited));
 27     for(int i=0;i<=n;i++) ve[i].clear();
 28 }
 29
 30 bool cmp(Edge a,Edge b){     //把路径按照最近公共祖先的深度从大到小排序
 31     return a.w>b.w;
 32 }
 33 void bfs(int ss){        //bfs求深度dep[]和向上走的步数f[][](在线算法)
 34     queue<int>Q;
 35     dep[ss]=1;
 36     f[ss][0]=1;
 37     Q.push(ss);
 38     int u, v, i;
 39     while(!Q.empty()){
 40         u=Q.front();
 41         Q.pop();
 42         for(i=1;i<M;i++) f[u][i]=f[f[u][i-1]][i-1];
 43         for(i=0;i<ve[u].size();i++){
 44             v=ve[u][i];
 45             if(v!=f[u][0]){
 46                 dep[v]=dep[u]+1;
 47                 f[v][0]=u;
 48                 Q.push(v);
 49             }
 50         }
 51     }
 52 }
 53
 54 void dfs(int u){                //dfs把最近公共祖先结点以下的点全部visited使得这条路径全部visited
 55     int v, i;
 56     visited[u]=1;
 57     for(i=0;i<ve[u].size();i++){
 58         v=ve[u][i];
 59         if(dep[v]>dep[u]&&!visited[v]){
 60             dfs(v);
 61         }
 62     }
 63 }
 64
 65 int lca(int x,int y){        //求x和y的最近公共祖先
 66     if(dep[x]<dep[y]) swap(x,y);
 67     int i, k;
 68     k=dep[x]-dep[y];
 69     for(i=0;i<M;i++){
 70         if(1<<i&k) x=f[x][i];
 71     }
 72     if(x==y) return x;
 73     for(i=M-1;i>=0;i--){
 74         if(f[x][i]!=f[y][i]){
 75             x=f[x][i];
 76             y=f[y][i];
 77         }
 78     }
 79     return f[x][0];
 80 }
 81
 82 main()
 83 {
 84     int x, y;
 85     int i, j, k, ans;
 86     while(scanf("%d %d",&n,&m)==2){
 87         init();
 88         for(i=1;i<n;i++){
 89             scanf("%d %d",&x,&y);
 90             ve[x].push_back(y);
 91             ve[y].push_back(x);
 92         }
 93         bfs(1);
 94         for(i=0;i<m;i++){
 95             scanf("%d %d",&x,&y);
 96             int ff=lca(x,y);
 97         //    printf("%d\n",ff);
 98             e[i]=Edge(x,y,ff,dep[ff]);
 99         }
100         sort(e,e+m,cmp);
101         ans=0;
102         for(i=0;i<m;i++){
103             if(!visited[e[i].u]&&!visited[e[i].v]){  //两个端点没有被visited那么整条路径也没被visited,想一想为什么
104                     dfs(e[i].f);
105                 ans++;
106             }
107         }
108         printf("%d\n",ans);
109     }
110 }

HDU 4912 LCA+贪心,布布扣,bubuko.com

时间: 2024-10-13 16:02:21

HDU 4912 LCA+贪心的相关文章

HDU 4912 lca贪心

Paths on the tree Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others) Total Submission(s): 297    Accepted Submission(s): 93 Problem Description bobo has a tree, whose vertices are conveniently labeled by 1,2,-,n. Th

HDU 4912 LCA+策略

点击打开链接 题意:给了一个树,然后m条路径,问最多可以选多少条路径而没有一个点是重复使用的,如第二组样例,3条路径是4-2-5和6-3-7和2-1-3,那么只能选前两个使得所选路径最多 思路:没啥思路,看了正解竟然是LCA+贪心,好嘛可以这样考虑,对于所有的可选路径,我们先选择最下面的对上面是没有影响的,那么我们可以对每条路经的最上面的那个点进行排序,就按深度由大到小排序,然后这个最上面的点不就是LCA嘛,然后因为是由下到上的,那么对于每次之后就要将以LCA为根的子树节点全部标记,因为它作为深

HDU 4912 Paths on the tree LCA 排序贪心

lca... 排个序然后暴力保平安 _(:зゝ∠)_ #pragma comment(linker, "/STACK:102400000,102400000") #include"cstdio" #include"iostream" #include"set" #include"queue" #include"string.h" using namespace std; #define

hdu 4912 Paths on the tree(树链剖分+贪心)

题目链接:hdu 4912 Paths on the tree 题目大意:给定一棵树,和若干个通道,要求尽量选出多的通道,并且两两通道不想交. 解题思路:用树链剖分求LCA,然后根据通道两端节点的LCA深度排序,从深度最大优先选,判断两个节点均没被标 记即为可选通道.每次选完通道,将该通道LCA以下点全部标记. #pragma comment(linker, "/STACK:1024000000,1024000000") #include <cstdio> #include

HDU 4912 Paths on the tree

http://acm.hdu.edu.cn/showproblem.php?pid=4912 题意:给一棵树,再给一些路径,求最多有多少条路径不相交. 题解:主要是贪心的想法.用LCA处理出路径的层数,然后从最深处的节点往上找.因为节点越深,对其他路径影响度越小,相交的可能性越低.需要手动扩栈. 1 #pragma comment(linker, "/STACK:1024000000,1024000000") 2 #include <iostream> 3 #include

HDU 2586 + HDU 4912 最近公共祖先

先给个LCA模板 HDU 1330(LCA模板) #include <cstdio> #include <cstring> #define N 40005 struct Edge{ int x,y,d,ne; }; Edge e[N*2],e2[N*2]; int be[N],be2[N],all,all2,n,m; bool vis[N]; int fa[N]; int ancestor[N][3]; int dis[N]; void add(int x, int y, int

hdu 4912 Paths on the tree(树链拆分+贪婪)

题目链接:hdu 4912 Paths on the tree 题目大意:给定一棵树,和若干个通道.要求尽量选出多的通道,而且两两通道不想交. 解题思路:用树链剖分求LCA,然后依据通道两端节点的LCA深度排序,从深度最大优先选.推断两个节点均没被标 记即为可选通道. 每次选完通道.将该通道LCA下面点所有标记. #pragma comment(linker, "/STACK:1024000000,1024000000") #include <cstdio> #includ

hdu 4869 Task(贪心)

题目链接:hdu 4869 Task 题目大意:有n台机器,m个任务,每个机器和任务都有有xi和yi,要求机器的xi,yi均大于等于任务的xi和yi才能执行任务.每台机器一天只能执行一个任务.要求完成的任务数尽量多,并且说金额尽量大.完成每个任务的金额为xi?500+yi?2 解题思路:贪心,mach[i][j]表示等级为i,时间为j的机器数量,task[i][j]表示等级为i,时间为j的机器数量.每次优先减少i,因为对应等级减少100,对应的金额代价也不会减少超过500(即时间减少1). 每次

hdu4912 Paths on the tree --- LCA贪心

给一棵n个结点的树,m条路径的起点和终点, 问至多可以选择多少条路径使其两两间没有公共点. 这题的主要问题是, 1.如何判断两条路径上没有交点 2.按什么策略来选 看上去感觉是最大匹配问题,但nm的范围较大问题1无法高效的解决. 画个图发现可能和LCA有关,但比赛时不知道这到底有什么用,完全没想贪心. 要选择尽量多,就是要尽量避免冲突. 我们选择一个点作为根,把给的边画出来建树就可以发现,尽量选深度大的路径可以使冲突尽量小. 于是把路径按LCA深度由大到小排序,依次和之前不冲突就可以选. 下面就