标签:using += div 16px test bsp style ring turn
<题目链接>
题目大意:
给你一棵树,然后进行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】
标签:using += div 16px test bsp style ring turn
原文地址:https://www.cnblogs.com/00isok/p/9824517.html