sicily 2377 Ants Colony 【LCA Tarjan算法】

  周赛第二次的题目。传说中的最近公共祖先问题(LCA),用Tarjan算法可以过,但注意结果超int.
  从题意可以看出这些colony之间构成了一棵树的关系,用Tarjan算法找出每对查询的顶点u,v的公共祖先ancestor,则u,v之间的距离就是dist[u]+dist[v]-2*dist[ancestor],关系显而易见,会者不难。
View Code
   
     
#include < iostream >
#include
< stdio.h >
#include
< vector >

using namespace std;
const int MAX = 100001 ;
struct Edge
{
int end; int dis;
Edge(
int e, int d): end(e),dis(d) {}
};
struct Quer
{
int v; int count;
Quer(
int vv, int c): v(vv),count(c) {}
};
vector
< Edge > Graph[MAX];
vector
< Quer > query[MAX];
bool vis[MAX];
int fa[MAX],n,q;
long long dist[MAX],ans[MAX];

void init()
{
int i;

for (i = 0 ;i <= n; ++ i)
{
Graph[i].clear();
dist[i]
= 0 ;
fa[i]
= i;
vis[i]
= false ;
}
for (i = 0 ;i <= MAX; ++ i) query[i].clear();
}

int Findset( int x)
{
while (fa[x] != x)
{
x
= fa[x];
}

return x;
}

void Tarjan( int now, long long cur_dis)
{
int i,end,dis,v,count;

vis[now]
= true ; dist[now] = cur_dis; fa[now] = now;

for (i = 0 ;i < query[now].size(); ++ i)
{
v
= query[now][i].v; count = query[now][i].count;

if (vis[v])
{
ans[count]
= dist[now] + dist[v] - 2 * dist[Findset(v)];
}
}

for (i = 0 ;i < Graph[now].size(); ++ i)
{
end
= Graph[now][i].end; dis = Graph[now][i].dis;

if ( ! vis[end])
{
Tarjan(end,cur_dis
+ dis);
fa[end]
= now;
}
}
}

int main()
{
int i,u,v,d;

while (scanf( " %d " , & n) && n)
{
init();

for (i = 1 ;i < n; ++ i)
{
scanf(
" %d %d " , & v, & d);
Graph[v].push_back(Edge(i,d));
Graph[i].push_back(Edge(v,d));
}

scanf(
" %d " , & q);
for (i = 0 ;i < q; ++ i)
{
scanf(
" %d %d " , & u, & v);
query[u].push_back(Quer(v,i));
query[v].push_back(Quer(u,i));
}

Tarjan(
0 , 0 );

for (i = 0 ;i < q; ++ i)
{
if (i) printf( " " );
cout
<< ans[i];
}
printf(
" \n " );
}

return 0 ;
}

你可能感兴趣的:(ant)