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