hdu 2874(LCA + 节点间距离)

解题思路:Tarjan离线处理


一篇介绍LCA的很好的博客:http://www.cppblog.com/menjitianya/archive/2015/12/10/212447.html


#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;

const int maxn = 10005;
struct Edge
{
	int k,next,cost;
}edge[maxn<<1];
struct Ask
{
	int k,next,id;
}ask[maxn<<1];
int n,m,c,cnt1,cnt2,pre[maxn],head[maxn];
int color[maxn],ans[maxn],dis[maxn],fa[maxn];
bool vis[maxn];

int find(int x)
{
	if(fa[x] == x) return x;
	else return fa[x] = find(fa[x]);
}

void addedge(int u,int v,int cost)
{
	edge[cnt1].k = v;
	edge[cnt1].cost = cost;
	edge[cnt1].next = pre[u];
	pre[u] = cnt1++;
}

void addask(int u,int v,int id)
{
	ask[cnt2].id = id;
	ask[cnt2].k = v;
	ask[cnt2].next = head[u];
	head[u] = cnt2++;
}

void Tarjan(int u,int root,int len)
{
	vis[u] = true;
	fa[u] = u;
	dis[u] = len;
	for(int i = pre[u]; i != -1; i = edge[i].next)
	{
		int v = edge[i].k;
		if(vis[v]) continue;
		Tarjan(v,root,len + edge[i].cost);
		fa[v] = u;
	}
	color[u] = root;
	for(int i = head[u]; i != -1; i = ask[i].next)
	{
		int v = ask[i].k;
		if(color[v] == root)
		{
			int ancestor = find(v);
			ans[ask[i].id] = dis[u] + dis[v] - 2*dis[ancestor];
		}
	}
}

int main()
{
	int u,v,cost;
	while(scanf("%d%d%d",&n,&m,&c)!=EOF)
	{
		memset(pre,-1,sizeof(pre));
		memset(head,-1,sizeof(head));
		cnt1 = cnt2 = 0;
		for(int i = 1; i <= m; i++)
		{
			scanf("%d%d%d",&u,&v,&cost);
			addedge(u,v,cost);
			addedge(v,u,cost);
		}
		for(int i = 1; i <= c; i++)
		{
			scanf("%d%d",&u,&v);
			addask(u,v,i);
			addask(v,u,i);
		}
		memset(vis,false,sizeof(vis));
		memset(color,0,sizeof(color));
		memset(ans,-1,sizeof(ans));
		for(int i = 1; i <= n; i++)
			if(vis[i] == false)
				Tarjan(i,i,0);
		for(int i = 1; i <= c; i++)
		{
			if(ans[i] == -1)
				printf("Not connected\n");
			else printf("%d\n",ans[i]);
		}
	}
	return 0;
}


你可能感兴趣的:(LCA)