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 <cstring>
  4 #include <cstdio>
  5 #include <cstdlib>
  6 #include <cmath>
  7 #include <string>
  8 #include <vector>
  9 #include <list>
 10 #include <map>
 11 #include <queue>
 12 #include <stack>
 13 #include <bitset>
 14 #include <algorithm>
 15 #include <numeric>
 16 #include <functional>
 17 #include <set>
 18 #include <fstream>
 19
 20 using namespace std;
 21
 22 const int INF=0xfffffff;
 23 const int maxn=100010;
 24
 25 struct edge
 26 {
 27     int v,next;
 28 }G[maxn*2];
 29 struct node
 30 {
 31     int u,v,id;
 32 }es[maxn];
 33 int head[maxn],idx;
 34 int LCA[maxn],par[maxn],d[maxn];
 35 bool used[maxn];
 36 int parent[maxn];
 37 int depth[maxn];
 38 vector<pair<int,int> >query[maxn];
 39
 40 int find(int x)
 41 {
 42     return x==par[x]?x:par[x]=find(par[x]);
 43 }
 44
 45 void build(int u,int v)
 46 {
 47     G[idx].v=v;
 48     G[idx].next=head[u];
 49     head[u]=idx++;
 50 }
 51
 52 void add_edge(int u,int v)
 53 {
 54     build(u,v);
 55     build(v,u);
 56 }
 57
 58 void dfs(int u,int root)
 59 {
 60     par[u]=u;
 61     pair<int,int>PI;
 62     for(int i=0;i<(int)query[u].size();i++)
 63     {
 64         PI=query[u][i];
 65         if(d[PI.first]==-1) continue;
 66         LCA[PI.second]=find(PI.first);
 67     }
 68     for(int k=head[u];k!=-1;k=G[k].next)
 69     {
 70         int v=G[k].v;
 71         if(v==root) continue;
 72         d[v]=d[u]+1;
 73         dfs(v,u);
 74         par[v]=u;
 75     }
 76 }
 77
 78 bool cmp(node& a,node& b)
 79 {
 80     int u=LCA[a.id];
 81     int v=LCA[b.id];
 82     return d[u]>d[v];
 83 }
 84
 85 void init(int n)
 86 {
 87     memset(used,0,sizeof(used));
 88     memset(head,-1,sizeof(head));
 89     idx=0;
 90     memset(d,-1,sizeof(d));
 91     for(int i=0;i<=n;i++) query[i].clear();
 92 }
 93
 94 void dfs_res(int u)
 95 {
 96     used[u]=true;
 97     for(int k=head[u];k!=-1;k=G[k].next)
 98     {
 99         int v=G[k].v;
100         if(used[v]||d[v]<d[u]) continue;
101         dfs_res(v);
102     }
103 }
104
105 int main()
106 {
107     //freopen("/Users/apple/Desktop/暑假/30/30/in","r",stdin);
108     int N,M;
109     while(scanf("%d%d",&N,&M)!=EOF)
110     {
111         init(N);
112         for(int i=1;i<N;i++)
113         {
114             int u,v;
115             scanf("%d%d",&u,&v);
116             add_edge(u,v);
117         }
118         for(int i=0;i<M;i++)
119         {
120             int u,v;
121             scanf("%d%d",&u,&v);
122             query[u].push_back(make_pair(v,i));
123             query[v].push_back(make_pair(u,i));
124             es[i].u=u;
125             es[i].v=v;
126             es[i].id=i;
127         }
128         d[1]=0;
129         dfs(1,-1);
130         sort(es,es+M,cmp);
131         int res=0;
132         for(int i=0;i<M;i++)
133         {
134             if(!used[es[i].u]&&!used[es[i].v])
135             {
136                 res++;
137                 dfs_res(LCA[es[i].id]);
138             }
139         }
140         printf("%d\n",res);
141     }
142     return 0;
143 }

HDU 4912 Paths on the tree

时间: 2024-08-10 21:15:35

HDU 4912 Paths on the tree的相关文章

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 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> #includ

HDU 4912 Paths on the tree(LCA+贪心)

题目链接 Paths on the tree 来源  2014 多校联合训练第5场 Problem B 题意就是给出m条树上的路径,让你求出可以同时选择的互不相交的路径最大数目. 我们先求出每一条路径(u, v)中u和v的LCA:w,按照路径的w的深度大小deep[w]对所有的路径排序. deep[w]越大,排在越前面. 然后从第一条路径开始一次处理,看c[u]和c[v]是否都没被标记过,如果都没被标记过则我们把这条路径选上,把答案加1. 同时标记以w为根的子树的节点为1,方便后续对c数组的查询

hdu 4912 Paths on the tree(lca+馋)

意甲冠军:它使树m路径,当被问及选择尽可能多的路径,而这些路径不相交. 思考:贪心,比較忧伤.首先求一下每对路径的lca.依照lca的层数排序.在深一层的优先级高.那么就能够贪心了,每次选择层数最深的那一个,假设两个端点没有被标记,那么就选择这条路径,把lca的子树都标记掉. 代码: #pragma comment(linker, "/STACK:1024000000,1024000000") #include<iostream> #include<cstdio>

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 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

hdu4912 Paths on the tree --- LCA贪心

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

hdu 4863 Centroid of a Tree 树dp

代码来自baka.. #include<iostream> #include<cstdio> #include<cstring> #include<string> #include<algorithm> #include<map> #include<queue> #include<stack> #include<set> #include<cmath> #include<vecto