Time Limit: 20001000 MS (Java/Others)

# Problem

The structure of the computer room in Northeastern University is pretty miraculous. There are $n$ servers, some servers connect to the gateway whose $IP$ address is $0$ directly. All servers are connected with each other by $n$ netting twines. It is said that this structure is favorable for maintaining physical problem of servers. But because of an unexpected rainstorm, the computer room was destroyed by a terrible thunderclap! Our maintainer Bittersweet found that many servers were not able to be visited, so he hurried to the computer room to lookup the reason. After several hours, Bittersweet realized that some net gape of servers were broken by thunderclap. However, there were too many servers to find out all the broken net gapes quickly. So he came up with an idea to assess the damaged condition roughly. Bittersweet decided to turn on some servers and ping other servers randomly, then record the unsuccessful pairs of servers. Now he need a program to analyze the record to confirm what is the minimum number of servers whose net gape was destroyed by thunderclap. Can you help him to complete this work?

## Input

There are at most $20$ test cases. In each test case, the first line is an integer $n (3≤n≤10^4)$, denoting the number of servers. The $IP$ address of these servers is $1…n$. Then follows $n$ lines, each line contains two integers $u$ and $v$ $(0≤u,v≤n)$, denoting that the server whose $IP$ address $is$ u is connected with the server whose $IP$ address is$v$ by netting twine initially. After those, there is one line contains only an integer $p (p≤50000)$, denoting the number that Bittersweet uses ping. Then follows p lines, each line contains two integers $U$ and $V$ , denoting when using server $U$ to ping server $V$, it returned unsuccessful.

## Output

A single integer $x$ in a line, denoting at least $x$ servers whose net gape were broken.

## Sample Input

4 1 0 4 2 2 0 3 2 2 1 3 2 1

1

## Source

2017 ACM/ICPC Asia Regional Shenyang Online

# Code

  1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90  //好题 lca+贪心 //题意：给出一棵有根树根节点标号 0，给出k个点对 (u,v)表示从u到v的路径(含u,v)上有一点坏掉， //问最少坏掉几个点 #include using namespace std; const int maxn = 1e4 + 7; struct query { int u,v,dep,lca;}; bool operator <(query a, query b)//排序lca深度 {return a.dep que; #define clr(a,b) memset(a,b,sizeof(a)); bool vis[maxn]; namespace LCA { int head[maxn]; int edge_tot; struct {int to,next;}edge[maxn<<1]; void addedge(int u,int v) { edge[edge_tot].to = v; edge[edge_tot].next = head[u]; head[u] = edge_tot ++; } int son[maxn],dep[maxn],fa[maxn],id[maxn],sz[maxn],Top[maxn]; int cnt; void dfs(int u,int pre,int d) { dep[u] = d; fa[u] = pre; sz[u] = 1; for(int i = head[u]; ~i; i = edge[i].next) { int v = edge[i].to; if(v != pre) { dfs(v,u,d+1); sz[u]+=sz[v]; if(son[u]==-1 || sz[v]>sz[son[u]]) son[u]=v; } } } void dfs2(int u,int sp) { Top[u] = sp;id[u] = cnt ++; if(son[u]==-1) return; dfs2(son[u], sp); for(int i=head[u]; ~i; i =edge[i].next) { int v = edge[i].to; if(v != son[u] && v != fa[u])dfs2(v,v); } } int LCA(int x,int y) { for(;Top[x]!=Top[y];dep[Top[x]]>dep[Top[y]]?x=fa[Top[x]]:y=fa[Top[y]]){} return dep[x]LCA::dep[u]) dfs(v); } } int main() { int n; while(scanf("%d",&n)!=EOF) { LCA::init();clr(vis,0);while(!que.empty())que.pop(); int ans = 0; for(int i=1;i<=n;i++) { int u,v;scanf("%d%d",&u,&v);//注意起点从0开始 LCA::addedge(++u,++v);LCA::addedge(v,u); } LCA::dfs(1,0,0);LCA::dfs2(1,1); int q;scanf("%d",&q); while(q--) { int u,v,lca,dep; scanf("%d %d",&u,&v); lca = LCA::LCA(++u,++v); dep = LCA::dep[lca]; que.push(query{u,v,dep,lca}); } while(!que.empty()) { int u = que.top().u, v = que.top().v; int lca = que.top().lca;que.pop(); if(vis[u]||vis[v]) continue;//两段点已经访问过pass ans++;dfs(lca); } printf("%d\n",ans); } return 0; }