SDNU 1492.Problem_A LCA倍增算法

来源:互联网 发布:代驾软件 编辑:程序博客网 时间:2024/06/08 19:02

1492.Problem_A


Time Limit: 1000 MS    Memory Limit: 32768 KB


Description

SDNU ACM-ICPC Association is in a mess. If you join it, you should be in the shadow of a person. This person, we call him "dalao". For example, there are two rookies, C and D, rely on A. We can say that A is the closest dalao of rookies C and D.For another example, A have two heelers C and D, D have two heelers E and F.We can know that A is the closest dalao of E and C.

But with the growth of Association, we cannot find the closest dalao between two rookies. So we need your help.


Input

There will be a series of examples.

For each input, the first line contains two integers N. N means the number of people.

Followed by the N-1 lines, each line contains two integers A and B. It means that A is a dalao of B.

Then the next line, contains two integers A and B. It means that we want to know who is the closest dalao between A and B.


Output

For each input, you should output the name of the closest dalao.If you cannot find this dalao, you should output "I am so bad."


Sample Input

7
1 2
1 3
2 5
2 6
6 7
6 8
3 5

Sample Output

1

Hint
Remember that a rookie is also a dalao of itself
For example:
Input
3
1 2
2 3
2 3
Output
2


    选拔赛的一道题目,题意很好理解,简单说就是LCA(最近公共祖先),不过之前没怎么做过这类题目,所以也一直没有整理过自己的模板.....翻到一个dfs+ST的算法就直接敲了,然后....TLE了,才看到后面有更快的算法,不过离比赛结束还剩10分钟已经没时间了,所以就这样放弃了。结果比赛结束下来,敲的后面的倍增算法就A了.....早知道该先敲后面的说,哎呀好气啊。

    下面是AC代码:

#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>#include<queue>using namespace std;const int MAXN=10010;const int DEG=20;struct Edge{    int to,next;}edge[MAXN*2];int head[MAXN],tot;void addedge(int u,int v){    edge[tot].to=v;    edge[tot].next=head[u];    head[u]=tot++;}void init(){    tot=0;    memset(head,-1,sizeof(head));}int fa[MAXN][DEG];int deg[MAXN];void BFS(int root){    queue<int>que;    deg[root]=0;    fa[root][0]=root;    que.push(root);    while(!que.empty())    {        int tmp=que.front();        que.pop();        for(int i=1;i<DEG;i++)        {            fa[tmp][i]=fa[fa[tmp][i-1]][i-1];        }        for(int i=head[tmp];i!=-1;i=edge[i].next)        {            int v=edge[i].to;            if(v==fa[tmp][0])                continue;            deg[v]=deg[tmp]+1;            fa[v][0]=tmp;            que.push(v);        }    }}int LCA(int u,int v){    if(deg[u]>deg[v])        swap(u,v);    int hu=deg[u],hv=deg[v];    int tu=u,tv=v;    for(int det=hv-hu,i=0;det;det>>=1,i++)    {        if(det&1)            tv=fa[tv][i];    }    if(tu==tv)        return tu;    for(int i=DEG-1;i>=0;i--)    {        if(fa[tu][i]==fa[tv][i])            continue;        tu=fa[tu][i];        tv=fa[tv][i];    }    return fa[tu][0];}bool flag[MAXN];int main(){    int T;    int n;    int u,v;    while(scanf("%d",&n)!=EOF)    {        init();        memset(fa,0,sizeof(fa));        memset(deg,0,sizeof(deg));        memset(flag,false,sizeof(flag));        for(int i=1;i<n;i++)        {            scanf("%d%d",&u,&v);            addedge(u,v);            addedge(v,u);            flag[v]=true;        }        int root;        for(int i=1;i<=n;i++)        {            if(!flag[i])            {                root=i;                break;            }        }        BFS(root);        scanf("%d%d",&u,&v);        if(LCA(u,v)==0)            cout<<"I am so bad."<<endl;        else            cout<<LCA(u,v)<<endl;    }    return 0;}


1 0