题目:Closest Common Ancestors POJ - 1470
题意:找最近的公共祖先
代码:
#include<stdio.h>
#include<string.h>
#include<iostream>
using namespace std;
const int maxn = 5000;
const int maxq = 500010;
int F[maxn];
int Find(int x)
{
if(F[x] == -1)return x;
return F[x] = Find(F[x]);
}
void bing(int u, int v)
{
int t1 = Find(u);
int t2 = Find(v);
if(t1 != t2)
F[t1] = t2;
}
bool vis[maxn];
int ancestor[maxn];
struct Edge
{
int to, next;
} edge[maxn*2];
int head[maxn], tot;
void add(int u, int v) //链式前向星
{
edge[tot].to = v;
edge[tot].next = head[u];
head[u] = tot++;
}
struct Query
{
int q, next;
int index;
} query[maxq*2];
int answer[maxq];
int h[maxq];
int tt;
int Q;
void add_query(int u, int v, int index)
{
query[tt].q = v;
query[tt].next = h[u];
query[tt].index = index;
h[u] = tt++;
query[tt].q = u;
query[tt].next = h[v];
query[tt].index = index;
h[v] = tt++;
}
void init()
{
tot = 0;
memset(head, -1, sizeof(head));
tt = 0;
memset(h, -1, sizeof(h));
memset(vis, false, sizeof(vis));
memset(F, -1, sizeof(F));
memset(ancestor, 0, sizeof(ancestor));
}
void LCA(int u)
{
ancestor[u] = u;
vis[u] = true;
for(int i = head[u]; i != -1; i = edge[i].next)
{
int v = edge[i].to;
if(vis[v])continue;
LCA(v);
bing(u, v);
ancestor[Find(u)] = u;
}
for(int i = h[u]; i != -1; i = query[i].next)
{
int v = query[i].q;
if(vis[v])
{
answer[query[i].index] = ancestor[Find(v)];
}
}
}
bool flag[maxn];
int cn[maxn];
int main()
{
int n;
int v, u, k;
while(~scanf("%d", &n))
{
init();
memset(flag, false, sizeof(flag));
for(int i = 1; i <= n; i++)
{
scanf("%d:(%d)", &u, &k);
while(k--)
{
scanf("%d", &v);
flag[v] = true;
add(u, v);
add(v, u);
}
}
scanf("%d", &Q);
char ch1[2], ch2[2];
for(int i = 0; i < Q; i++)
{
scanf("%1s%d%d%1s",ch1,&u,&v,ch2);
//cout<<u<<" "<<v<<endl;
add_query(u, v, i);
}
int root = 0;
for(int i = 1; i <= n; i++)
{
//cout<<flag[i]<<endl;
if(!flag[i])
{
root = i;
break;
}
}
LCA(root);
memset(cn, 0, sizeof(cn));
for(int i = 0; i < Q; i++)
{
cn[answer[i]]++;
}
for(int i= 1; i <= n; i++)
{
if(cn[i] > 0)printf("%d:%d\n", i, cn[i]);
}
}
return 0;
}