1. 程式人生 > >POJ 1470 Closest Common Ancestors (模板題)(Tarjan離線)【LCA】

POJ 1470 Closest Common Ancestors (模板題)(Tarjan離線)【LCA】

clear pac push 公共祖先 back family ble lan tarjan

<題目鏈接>

題目大意:
給你一棵樹,然後進行q次詢問,然後要你統計這q次詢問中指定的兩個節點最近公共祖先出現的次數。

解題分析:
LCA模板題,下面用的是離線Tarjan來解決。並且為了代碼的簡潔,本代碼用的是vector存圖。

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<vector>
 5 
 6 using namespace std;
 7 const int N = 1100;
 8 
 9 vector<int>edge[N];
10 int query[N][N],father[N],count[N],indeg[N]; 11 bool vis[N]; 12 int n,m; 13 void init(){ 14 for(int i=1;i<=n;i++)edge[i].clear(); 15 memset(query,0,sizeof(query)); 16 memset(vis,false,sizeof(vis)); 17 memset(count,0,sizeof(count)); 18 memset(indeg,0,sizeof(indeg)); 19 } 20 int find(int
x){ //找到根節點 21 if(x!=father[x]) 22 father[x]=find(father[x]); 23 return father[x]; 24 } 25 void Tarjan(int u){ 26 father[u]=u; 27 for(int i=0;i<edge[u].size();i++){ //得到該樹上所有節點的父子關系 28 int v=edge[u][i]; 29 Tarjan(v); 30 father[v]=u; 31 } 32 vis[u]=true
; 33 for(int i=1;i<=n;i++) 34 if(vis[i] && query[u][i]) 35 count[find(i)]+=query[u][i]; //最近公共祖先出現次數+1 36 } 37 int main(){ 38 while(~scanf("%d",&n)){ 39 init(); 40 int u,v; 41 for(int i=0;i<n;i++){ 42 scanf("%d:(%d)",&u,&m); 43 while(m--){ 44 scanf(" %d",&v); 45 edge[u].push_back(v); //建立有向邊 46 indeg[v]++; //統計入度,用於尋找根節點 47 } 48 } 49 scanf(" %d",&m); 50 for(int i=0;i<m;i++){ 51 scanf(" (%d %d)",&u,&v); 52 query[u][v]++; //將代查詢的節點也全部記錄下來 53 query[v][u]++; 54 } 55 for(int i=1;i<=n;i++) 56 if(indeg[i]==0){ 57 Tarjan(i); 58 break; 59 } 60 for(int i=1;i<=n;i++) 61 if(count[i]) 62 printf("%d:%d\n",i,count[i]); 63 } 64 return 0; 65 }

2018-10-21

POJ 1470 Closest Common Ancestors (模板題)(Tarjan離線)【LCA】