首页 > 其他分享 >hdu 2874(LCA + 节点间距离)

hdu 2874(LCA + 节点间距离)

时间:2023-05-29 22:37:27浏览次数:47  
标签:10005 hdu 2874 int 离线 maxn LCA include


解题思路: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;
}




标签:10005,hdu,2874,int,离线,maxn,LCA,include
From: https://blog.51cto.com/u_16143128/6374306

相关文章

  • hdu 4027(线段树)
    题意:给定100000个数,两种操作,0ij表示将ij这段的数字都开根号(向下取整),1ij表示查询ij之间的所有值的和。。。(所有的和都不超过64位)解题思路:这题要做区间的开平方操作,2^64最多可以做8次开平方操作,所以对于每个节点最多只有8次操作,这道题如果lazy思想的话就要保存每个区间被开平方......
  • hdu 3564(线段树+LIS)
    题意:给出1~n的插入顺序,要求每次插入之后的LIS解题思路:这道题确实挺难想的,我最开始想用树状数组每插入一个数就更新一次,如果这么想,那么你就输了。它这里的想法是先将1-n的最终位置都保存起来,然后再一个个去找LIS。这里有点离线算法的意思,至少了解到更新时可以先别急着处理。还有这里......
  • hdu 3874(树状数组+离线算法)
    解题思路:这道题和之前的题一样,查找[l,r]区间内不重复数字的和。可以利用离线算法,实际上离线算法为了解决在查找时出现的矛盾,因为每次询问的区间大小不同,如果单独处理的话可能会对之后的查询有影响,所以离线算法帮助我们把要查询的区间先按照右端点进行排序,因为在处理更靠右的区间时,......
  • hdu 4101(bfs+博弈)
    题意:题目的意思就是说两个人轮流玩游戏,给你一张地图,这个地图中间有一点-1代表宝藏,AliandBaba轮流走路,如果某一个人能够直接走到宝藏的话,那么他就赢了。地图上其它的点0代表空地,数字代表当前地点的石子当某一人拿石子的时候,他只能拿走一颗。问你谁最后能拿到宝藏;解题思路:宝藏位于-......
  • hdu 1510
    WhiteRectanglesTimeLimit:2000/1000MS(Java/Others)    MemoryLimit:65536/32768K(Java/Others)ProblemDescriptionYouaregivenachessboardmadeupofNsquaresbyNsquareswithequalsize.Someofthesquaresarecoloredblack,andthe......
  • hdu 2821
    题意:n*m的格子上有一些方块放在某些格子上,一个格子可能有几个方块,用'a'-'z'来表示方块数量。初始的时候可以选择任意空地作为Pusher初始点,Pusher选择一个方向,然后向这个方向前进直到遇到有方块的格子,Pusher把这个格子的方块清除一个,并把它向前推一格(向前不能出界),如果前面一格有方......
  • hdu 1534(差分约束)
    题意:安排计划,有4种约束方式,给出你这些时间的n个约束..如果计划是可行的,求出每一件事发生的最早时间..否则输出“impossible”..①.FAFaba要在b完成后完成..②.FASaba要在b开始前完成..③.SASaba要在b开始前开始..④.SAFaba要在b结束前开......
  • hdu 1532(最大流)
    解题思路:这是一道典型的模板题,直接套用EK算法即可。。。我感觉最大流的本质就是能否找到一个从源点到汇点的增广路径,并将其最小的边作为增加值,沿着增广路上的边进行更新。AC:#include<iostream>#include<cstdio>#include<cstring>#include<queue>usingnamespacestd;consti......
  • hdu 5074(简单dp)
    HatsuneMikuTimeLimit:2000/1000MS(Java/Others)    MemoryLimit:262144/262144K(Java/Others)ProblemDescriptionHatsuneMikuisapopularvirtualsinger.ItisverypopularinbothJapanandChina.Basicallyitisacomputersoftwarethata......
  • hdu 3303(线段树+抽屉原理)
    解题思路:这题利用了抽屉原理,即1-M之间的所有数与M+1的模都不相同。那么可以利用它将要查找所有区间分成[1,Y-1],[Y,2*Y-1],[2*Y,3*Y-1].........一直下去,直到所有的区间都被找一遍,然后就是保存最小的模即可。。。这样就肯定要找每个区间的最小的模,实际上这里可以利用线段树去找,只需......