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.

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

Author

Xiaoxu Guo (ftiasch)

一棵树,给出m条路径,然后问最多选择多少条路径,使得每两条路径之间没有 不论什么公共点,公共边。

把m条路径求出lca,然后依照lca深度从大到小排序,把路径上经过的点标记出来,贪心就可以。

代码:

#include <stdio.h>
#include <iostream>
#include <algorithm>
#include <sstream>
#include <stdlib.h>
#include <string.h>
#include <limits.h>
#include <string>
#include <time.h>
#include <math.h>
#include <queue>
#include <stack>
#include <set>
#include <map>
using namespace std;
#define INF 0x3f3f3f3f
#define eps 1e-8
#define pi acos(-1.0)
typedef long long ll;
const int maxn=100010;
int head[maxn],tol,fa[maxn][20],dep[maxn];
struct Edge{
    int next,to;
    Edge(int _next=0,int _to=0){
        next=_next;to=_to;
    }
}edge[10*maxn];
void addedge(int u,int v){
    edge[tol]=Edge(head[u],v);
    head[u]=tol++;
}
void bfs(int s){
    queue<int> q;
    dep[s]=0,fa[s][0]=s;
    q.push(s);
    while(!q.empty()){
        int u=q.front();
        q.pop();
        for(int i=1;i<20;i++)fa[u][i]=fa[fa[u][i-1]][i-1];
        for(int i=head[u];i!=-1;i=edge[i].next){
            int v=edge[i].to;
            if(v==fa[u][0])continue;
            fa[v][0]=u;
            dep[v]=dep[u]+1;
            q.push(v);
        }
    }
}
int LCA(int x,int y){
    if(dep[x]<dep[y])swap(x,y);
    for(int i=19;i>=0;i--)if((1<<i)&(dep[x]-dep[y]))x=fa[x][i];
    if(x==y)return x;
    for(int i=19;i>=0;i--)if(fa[x][i]!=fa[y][i])x=fa[x][i],y=fa[y][i];
    return fa[x][0];
}
struct QQ{
    int u,v,lca;
}pp[100100];
bool vis[100100];
int n,m;
bool cmp(QQ a,QQ b){
    return dep[a.lca]>dep[b.lca];
}
int main()
{
    while(~scanf("%d%d",&n,&m)){
        memset(head,-1,sizeof(head));
        tol=0;
        for(int i=1;i<n;i++){
            int u,v;
            scanf("%d%d",&u,&v);
            addedge(u,v);
            addedge(v,u);
        }
        bfs(1);
        for(int i=0;i<m;i++){
            scanf("%d%d",&pp[i].u,&pp[i].v);
            pp[i].lca=LCA(pp[i].u,pp[i].v);
        }
        sort(pp,pp+m,cmp);
        memset(vis,0,sizeof(vis));
        int ans=0;
        for(int i=0;i<m;i++){
            int lca=pp[i].lca,flag=1,u=pp[i].u,v=pp[i].v;
            if(vis[u]||vis[v]||vis[lca])continue;
            for(int j=u;j!=lca;j=fa[j][0])
                if(vis[j]){
                    flag=0;break;
                }
            for(int j=v;j!=lca;j=fa[j][0])
                if(vis[j]){
                    flag=0;break;
                }
            if(!flag)continue;
            ans++;
            vis[lca]=1;
            for(int j=u;j!=lca;j=fa[j][0])vis[j]=1;
            for(int j=v;j!=lca;j=fa[j][0])vis[j]=1;
        }
        printf("%d\n",ans);
    }
    return 0;
}
时间: 2024-10-16 10:07:00

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): 531    Accepted Submission(s): 182 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深度由大到小排序,依次和之前不冲突就可以选. 下面就