首页 > 其他分享 >POI2012RAN-Rendezvous

POI2012RAN-Rendezvous

时间:2024-04-25 09:04:48浏览次数:25  
标签:dep int POI2012RAN fa num que Rendezvous deg

POI #Year2012 #基环树 #lca

分类讨论

  • 如果 \(a,b\) 不联通, \(-1\)
  • 如果 \(a,b\) 在同一棵子树下,最优策略一定是 \(lca(a,b)\)
  • 如果 \(a,b\) 不在同一棵子树下,最优策略是 \(rt_a,rt_b\) 中的一个
// Author: xiaruize
const int N = 5e5 + 10;
#define endl '\n'
int head[N], to[N], nxt[N], egcnt;

void add(int u, int v)
{
	to[++egcnt] = v;
	nxt[egcnt] = head[u];
	head[u] = egcnt;
}

int n, q;
int fa[N][20];
// vector<int> g[N];
int deg[N];
queue<int> que;
int st[N];
int rt[N], num[N];
int dep[N];
int len[N];
int tot = 0;

void dfs(int x, int rot, int dp)
{
	dep[x] = dp;
	rt[x] = rot;
	num[x] = num[rot];
	for (int i = head[x]; i; i = nxt[i])
	{
		int v = to[i];
		if (!deg[v])
			dfs(v, rot, dp + 1);
	}
}

int lca(int u, int v)
{
	if (dep[u] < dep[v])
		swap(u, v);
	per(i, 19, 0) if (dep[fa[u][i]] >= dep[v])
		u = fa[u][i];
	if (u == v)
		return u;
	per(i, 19, 0) if (fa[u][i] != fa[v][i])
	{
		u = fa[u][i];
		v = fa[v][i];
	}
	return fa[u][0];
}

bool cmp(int a, int b, int c, int d)
{
	if (max(a, b) != max(c, d))
		return max(a, b) < max(c, d);
	if (min(a, b) != min(c, d))
		return min(a, b) < min(c, d);
	return a >= b;
}

void solve()
{
	cin >> n >> q;
	rep(i, 1, n)
	{
		cin >> fa[i][0];
		add(fa[i][0], i);
		deg[fa[i][0]]++;
	}
	rep(k, 1, 19)
		rep(i, 1, n)
			fa[i][k] = fa[fa[i][k - 1]][k - 1];
	rep(i, 1, n) if (!deg[i]) que.push(i);
	while (!que.empty())
	{
		auto x = que.front();
		que.pop();
		deg[fa[x][0]]--;
		if (!deg[fa[x][0]])
			que.push(fa[x][0]);
	}
	rep(i, 1, n)
	{
		if (!deg[i])
			continue;
		debug(i);
		if (!num[i])
		{
			num[i] = ++tot;
			int x = fa[i][0];
			st[i] = ++len[tot];
			while (x != i)
			{
				st[x] = ++len[tot];
				num[x] = tot;
				x = fa[x][0];
			}
		}
		dfs(i, i, 0);
	}
	while (q--)
	{
		int u, v;
		cin >> u >> v;
		if (num[u] != num[v])
		{
			cout << "-1 -1" << endl;
			continue;
		}
		if (rt[u] == rt[v])
		{
			int p = lca(u, v);
			cout << dep[u] - dep[p] << ' ' << dep[v] - dep[p] << endl;
		}
		else
		{
			int rt1 = rt[u], rt2 = rt[v];
			int tmp1 = dep[u] + (st[rt2] - st[rt1] + len[num[rt1]]) % len[num[rt1]];
			int tmp2 = dep[v] + (st[rt1] - st[rt2] + len[num[rt1]]) % len[num[rt1]];
			if (cmp(dep[u], tmp2, dep[v], tmp1))
				cout << dep[u] << ' ' << tmp2 << endl;
			else
				cout << tmp1 << ' ' << dep[v] << endl;
		}
	}
}

#ifndef ONLINE_JUDGE
bool end_of_memory_use;
#endif

signed main()
{
	// freopen(".in","r",stdin);
	// freopen(".out","w",stdout);
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	int testcase = 1;
	// cin >> testcase;
	while (testcase--)
		solve();
#ifndef ONLINE_JUDGE
	cerr << "Memory use:" << (&end_of_memory_use - &start_of_memory_use) / 1024.0 / 1024.0 << "MiB" << endl;
	cerr << "Time use:" << (double)clock() / CLOCKS_PER_SEC * 1000.0 << "ms" << endl;
#endif
	return 0;
}

标签:dep,int,POI2012RAN,fa,num,que,Rendezvous,deg
From: https://www.cnblogs.com/xiaruize/p/18156736

相关文章

  • [POI2012] Rendezvous 题解
    众所周知,\(lyh\)是一名压行大师,也是一名\(juruo\),所以他将他繁琐的方法用\(102\)行表现了出来……明显原题为基环内向树森林。首先用并查集计算连通块,不在一个连通块里的答案就是\(-1\-1\)。发现实际上答案就是以环为根节点,求\(lca\)的结果,求完后可以分为两种情况:根......
  • TIBCO.Rendezvous简单的发消息的过程
    C#代码实现发消息的过程.首先需要安装,添加引用,usingTIBCO.Rendezvous;然后其实就是简单4个步骤,即可把讯息发出去;开启环境->实例化NetTransport->生成需要发送的Message->transport.Send(msg);最后关闭环境;1//开启环境;2TIBCO.Rend......
  • [swin-trans]分布式训练的debug:ValueError: Error initializing torch.distributed us
    在用torch.distributed.init_process_group(backend='nccl',init_method='env://',world_size=world_size,rank=rank)时,出现1、ValueError:Errorinitializingtorch.distributedusingenv://rendezvous:environmentvariableMASTER_ADDRexpected,b......
  • P3533 [POI2012] RAN-Rendezvous 题解
    P3533[POI2012]RAN-Rendezvous题目大意:给定外向树森林,每次给定两个起始点,求两个点沿边移动最少步数相遇。\(n\)个点,\(n\)条边,并且每个点有唯一的出边,显然构成了多棵基环树,对于每个基环树分别处理:找出环上的点,因为要求支持求出任意两点距离,前缀和一下即可。对于询问,如果在两......
  • Rendezvous hashing算法介绍
    RendezvoushashingRendezvoushashing用于解决分布式系统中的分布式哈希问题,该问题包括三部分:Keys:数据或负载的唯一标识Values:消耗资源的数据或负载Servers:管理数据或负载的实体例如,在一个分布式系统中,key可能是一个文件名,value是文件数据,servers是连接网络的数据服务器,......
  • Pytorch rendezvous 分布式
    PyTorch中的rendezvous后端是一种服务,它帮助分布式训练作业中的进程相互发现并协商角色和等级。它还提供了一个屏障和一个一致的作业成员和状态视图。 rendezvous后端是作为torch.distributed.elastic.rendezvous.RendezvousHandler的子类实现的,它定义了创建、加入和销毁rendez......