problem
题目描述
如题,给定一棵有根多叉树,请求出指定两个点直接最近的公共祖先。
输入格式:
第一行包含三个正整数N、M、S,分别表示树的结点个数、询问的个数和树根结点的序号。
接下来N-1行每行包含两个正整数x、y,表示x结点和y结点之间有一条直接连接的边(数据保证可以构成树)。
接下来M行每行包含两个正整数a、b,表示询问a结点和b结点的最近公共祖先。
输出格式:
输出包含M行,每行包含一个正整数,依次为每一个询问的结果。
输入样例#1:
5 5 4
3 1
2 4
5 1
1 4
2 4
3 2
3 5
1 2
4 5
输出样例#1:
4
4
1
4
4
思路
数据量可以到500000点 500000询问 提交果然卡常了
1.读入可以用getchar优化(次要)
2.vector较链表在数据量大的时候是慢的(希望有大神可以系统的说明下这个vector的复杂度分析),可以用链式邻接表或者链式前向星模拟邻接表
代码示例(链式邻接表)
#include
using namespace std;
const int maxn=500010;struct Edge{int from,to;
}edges[2*maxn];const int maxlog=30;
int grand[maxn][maxlog];
int depth[maxn];
int n;
int s;
int root;
int cnt;struct EdgeNode{int adjvex;EdgeNode *next;
};struct AdList{int flag;EdgeNode *firstarc;
}G[maxn];void addEdge(int u,int v){edges[cnt].from=u;edges[cnt++].to=v;
代码示例(链式向前星)
#include
using namespace std;
const int maxn=500010;struct Edge{int from,to;
}edges[2*maxn];const int maxlog=30;
int grand[maxn][maxlog];
int head[2*maxn];
int depth[maxn];
int n;
int s;
int root;
int cnt;void addEdge(int u,int v){edges[cnt].from=v;edges[cnt].to=head[u];head[u]=cnt++;
}void init()
{cnt=0;memset(grand,0,sizeof(grand));memset(head,-1,sizeof(head));memset(depth,0,sizeof(depth));
}void dfs(int x)
{for(int i&#61;1;i<&#61;s;&#43;&#43;i){grand[x][i]&#61;grand[grand[x][i-1]][i-1];}for(int i&#61;head[x];i!&#61;-1;i&#61;edges[i].to){int tt&#61;edges[i].from;if(tt!&#61;grand[x][0]){depth[tt]&#61;depth[x]&#43;1;grand[tt][0]&#61;x;dfs(tt);}}
}int lca(int a,int b)
{if(depth[a]>depth[b]) swap(a,b);int dre&#61;depth[b]-depth[a];for(int i&#61;s;i>&#61;0;--i){if(dre&(1<if(a&#61;&#61;b) return a;for(int i&#61;s;i>&#61;0;i--)if(grand[a][i]!&#61;grand[b][i]){a&#61;grand[a][i],b&#61;grand[b][i];}return grand[a][0];
}int read()
{char ch&#61;&#39;*&#39;;while(!isdigit(ch&#61;getchar()));int num&#61;ch-&#39;0&#39;;while(isdigit(ch&#61;getchar())) num&#61;num*10&#43;ch-&#39;0&#39;;return num;
}int main()
{init();int query,u,v,w;scanf("%d %d %d",&n,&query,&root);s&#61;floor(log(n&#43;0.0)/log(2.0))&#43;1;for(int i&#61;1;i<&#61;n-1;&#43;&#43;i){u&#61;read();v&#61;read();addEdge(u,v);addEdge(v,u);}dfs(root);for(int i&#61;1;i<&#61;query;&#43;&#43;i){u&#61;read();v&#61;read();printf("%d\n",lca(u,v));}return 0;
}