hdu 2874

这道题题意很简单

给你一个森林,输入连通的点,最后给你多次询问,每次问输出两个点 s 和 t 之间的 距离

 

如果没连通就输出 Not contence....(总之是串英文)

有些丢人。。。不会写离线算法。。写了个在线算法。。。跑了 1700ms 。。。

 

 

 

还是很好搞的。。因为是森林。跑最短路会出事的。所以先用并查集建立集合关系。

输入s t 判断一下,之后正常的求出 dis[s] + dis[t] - 2 * dis[lca]

 

 

 

以下是 AC 代码。。。

#include
#include
#include
#include
using namespace std;
const int maxn = 1e5+5;
const int ins = 20;
int f[maxn][ins];
int pre[maxn];
int dis[maxn];
int dep[maxn];
struct node
{
	int to,nex,val;
}ed[maxn<<1];
int head[maxn],tot;
int n,m,q;
void add(int u,int v,int w)
{
	ed[++tot].to = v;
	ed[tot].val = w;
	ed[tot].nex = head[u];
	head[u] = tot;
}
void init()
{
	tot = 0;
    for(int i = 0; i <= n; i++)
		pre[i] = i;
    memset(head , -1, sizeof(head));
    memset(f, 0, sizeof(f));
    memset(dis, 0, sizeof(dis));
    memset(dep, 0, sizeof(dep));
}
int findd(int x)
{
	return x == pre[x] ? x : pre[x] = findd(pre[x]);
}
void merage(int a,int b)
{
	int aa = findd(a), bb = findd(b);
    if(aa != bb)
        pre[aa] = bb;
}
void dfs(int x,int p,int d)
{
	f[x][0] = p;
	dep[x] = dep[p] + 1;
	dis[x] = d;
	for(int i=1;i<=19;i++)
	{
		f[x][i] = f[f[x][i - 1]][i - 1];
	}
	for(int i=head[x];~i;i=ed[i].nex)
	{
		int v = ed[i].to;
		if(v != p)
		{
			dfs(v, x, dis[x] + ed[i].val);
		}
	}
}
int lca(int a,int b)
{
	if(dep[a] > dep[b])
	swap(a,b);
	for(int i=19;i>=0;i--)
	{
		if(dep[f[b][i]] >= dep[a])
		b = f[b][i];
	}
	if(a == b)
	return a;
	for(int i=19;i>=0;i--)
	{
		if(f[a][i] != f[b][i])
		{
			a = f[a][i];
			b = f[b][i];
		}
	}
	return f[a][0];
}
int main()
{
	while(scanf("%d%d%d",&n,&m,&q) == 3)
	{
		int u,v,w;
		init();
		for(int i=0;i

 

你可能感兴趣的:(HDU)