1492.Problem_A
Time Limit: 1000 MS Memory Limit: 32768 KB
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.
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."
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;
}