Paths on the tree
Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Others)
Total Submission(s): 600 Accepted Submission(s): 210
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.
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≤10 5). Each of the following (n - 1) lines contain 2 integers a i,b i denoting an edge between vertices a i and b i (1≤a i,b i≤n). Each of the following m lines contain 2 integers u i,v i denoting a path between vertices u i and v i (1≤u i,v i≤n).
The first line contains n,m (1≤n,m≤10 5). Each of the following (n - 1) lines contain 2 integers a i,b i denoting an edge between vertices a i and b i (1≤a i,b i≤n). Each of the following m lines contain 2 integers u i,v i denoting a path between vertices u i and v i (1≤u i,v i≤n).
Output
For each tests:
A single integer, the maximum number of paths.
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)
Source
Recommend
题意:
给一n<=10000个点的树,和m<=10000条路径(用起点和终点表示),问最多可以选择多少条路径,使得所选的任意两条路径之间没有公共点。
思路:
直观的感觉就是选择尽量靠下面的,但是路径之间的高度怎么比较呢
路径的最高点就是起点和终点的LCA,根据这个LCA的按照深度又深到浅选择,不可选择则跳过,可以选择则选择,然后把该路径最高点即前面说的LCA下面的所有子树标记为不可以选择,这样就可以O(1)判断一条路径是否可以选择
#include <cstdio>
#include <iostream>
#include <vector>
#include <algorithm>
#include <cstring>
#include <string>
#include <map>
#include <cmath>
#include <queue>
#include <set>
#pragma comment(linker, "/STACK:102400000")
using namespace std;
//#define WIN
#ifdef WIN
typedef __int64 LL;
#define iform "%I64d"
#define oform "%I64d\n"
#define oform1 "%I64d"
#else
typedef long long LL;
#define iform "%lld"
#define oform "%lld\n"
#define oform1 "%lld"
#endif
#define S64I(a) scanf(iform, &(a))
#define P64I(a) printf(oform, (a))
#define P64I1(a) printf(oform1, (a))
#define REP(i, n) for(int (i)=0; (i)<n; (i)++)
#define REP1(i, n) for(int (i)=1; (i)<=(n); (i)++)
#define FOR(i, s, t) for(int (i)=(s); (i)<=(t); (i)++)
const int INF = 0x3f3f3f3f;
const double eps = 10e-9;
const double PI = (4.0*atan(1.0));
const int maxn = 100000 + 20;
vector<int> G[maxn];
vector<int> query[maxn];
struct Path {
int u, v, lca, deep;
};
bool cmp(Path a, Path b) {
return a.deep > b.deep;
}
Path paths[maxn];
int fa[maxn];
int deep[maxn];
int vis[maxn];
int find(int x) {
return x==fa[x] ? x : fa[x] = find(fa[x]);
}
void Union(int u, int v) {
int fu = find(u);
int fv = find(v);
fa[fv] = fu;
}
void dfs(int u) {
fa[u] = u;
vis[u] = 1;
for(int i=0; i<G[u].size(); i++) {
int v = G[u][i];
if(vis[v]) continue;
deep[v] = deep[u] + 1;
dfs(v);
Union(u, v);
}
for(int i=0; i<query[u].size(); i++) {
int ii = query[u][i];
int v = paths[ii].u^paths[ii].v^u;
if(vis[v]) {
paths[ii].lca = find(v);
paths[ii].deep = deep[paths[ii].lca];
}
}
}
void setc(int u) {
vis[u] = 1;
for(int i=0; i<G[u].size(); i++) {
int v = G[u][i];
if(vis[v] || deep[v] <= deep[u]) continue;
setc(v);
}
}
int main() {
int n, m;
while(scanf("%d%d", &n, &m) != EOF) {
for(int i=0; i<=n; i++) G[i].clear();
for(int i=0; i<=m; i++) query[i].clear();
for(int i=1; i<n; i++) {
int u, v;
scanf("%d%d", &u, &v);
G[u].push_back(v);
G[v].push_back(u);
}
for(int i=0; i<m; i++) {
scanf("%d%d", &paths[i].u, &paths[i].v);
query[paths[i].u].push_back(i);
query[paths[i].v].push_back(i);
}
memset(vis, 0, sizeof(vis));
deep[1] = 1;
dfs(1);
sort(paths, paths+m, cmp);
int ans = 0;
memset(vis, 0, sizeof(vis));
for(int i=0; i<m; i++) {
int u = paths[i].u;
int v = paths[i].v;
int lca = paths[i].lca;
if(vis[u] || vis[v]) continue;
ans++;
setc(lca);
}
printf("%d\n", ans);
}
return 0;
}