列表

详情


NC227021. 都市的柏油路太硬(T4)

描述

都市的柏油路太硬

在大都市有一张 n 个城市和 m 条双向泊油路(保证联通),每条泊油路上有长度。

夵森派 觉得没有意思,便定义两城市 A,B 之间的权值为 A 到 B 的所有泊油路上最长的泊油路的最小值(这里解释下权值的定义: A->B 的某条路径上边权构成一个集合,集合的价值为集合中最大值,而 A,B 的权值为min{A->B 路径构成集合的权值})

夵森派 用点与点之间的权值(即 条边)建起了一颗最小生成树,夵森派 会询问这棵最小生成树上两点之间路径上的最大一条边的权值,而你的任务就是回答 夵森派 的问题。

为了减少输入量,Q 组询问使用给定随机数生成器生成。
为了减少输出量,在 Q 组询问后输出所有答案的异或和。

输入描述

输入的第一行包含 N 和 M。
接下来 M 行为三个整数A,B,C,表示 A 到 B 之间有一条长度为 C 的双向泊油路。
接下来一个整数 Q,a1,a2,代表询问总数和随机树生成器的两个参数。注意 a1,a2 可能达到 unsigned long long 类型。

关于随机数生成器:

typedef unsigned long long ull; ull myRand(ull &k1, ull &k2){     ull k3 = k1, k4 = k2;     k1 = k4;     k3 ^= (k3 <<23);     k2 = k3 ^ k4 ^ (k3 >>17) ^ (k4 >>26);     return k2 + k4; } pair<int,int>myRanq(ull&k1,ull&k2,int MAXN){     int x=myRand(k1,k2)%MAXN+1,y=myRand(k1,k2)%MAXN+1;     if(x>y)return make_pair(y,x);     else return make_pair(x,y); }

调用时传入 myRanq(a1,a2,n),会返回一个 pair<int,int> 类表示询问的两个端点。

输出描述

输出 1 行,表示所有答案的异或和。

示例1

输入:

7 11
2 4 2
1 4 3
7 2 2
3 4 3
5 7 5
7 3 3
6 1 1
6 3 4
2 4 3
5 6 3
7 2 1

10
114 514

输出:

3

说明:

N≤1e5,M≤5e5,Q≤1e7,C≤2e9。提示:由于读入量较大,请选择较快的读入方式。

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++ 解法, 执行用时: 1743ms, 内存消耗: 62268K, 提交时间: 2021-09-11 11:15:56

#include <bits/stdc++.h>
#define ull unsigned long long
using namespace std;
const int N=4e5+10;
int dfn[N],st[N][23],dep[N],fa[N],n,m,node,cnt,val[N];
vector<int> g[N];
ull myRand(ull &k1, ull &k2)
{
    ull k3=k1,k4=k2;
    k1=k4;
    k3^=(k3<<23);
    k2=k3^k4^(k3>>17)^(k4>>26);
    return k2+k4;
}
pair<int,int>myRanq(ull&k1,ull&k2,int MAXN){
    int x=myRand(k1,k2)%n+1,y=myRand(k1,k2)%n+1;
    if(x>y)return make_pair(y,x);
    else return make_pair(x,y);
}

struct Edge
{
	int u,v,w;
}e[N*2];
bool cmp(Edge x,Edge y){return x.w<y.w;}
int find(int x)
{
	if(x==fa[x]) return x;
	return fa[x]=find(fa[x]);
}
void dfs(int p,int depth)
{
	dfn[p]=++cnt;st[cnt][0]=p;dep[p]=depth;
	for(int i=0;i<g[p].size();i++)
	{
		int to=g[p][i];
		dfs(to,depth+1);
		st[++cnt][0]=p;
	}
}
void kruskal()
{
	int node=n;
	for(int i=1;i<=2*n;i++) fa[i]=i;
	sort(e+1,e+m+1,cmp);
	for(int i=1;i<=m;i++)
	{
		int u=find(e[i].u),v=find(e[i].v);
		if(u==v) continue;
		fa[u]=fa[v]=++node;val[node]=e[i].w;
		g[node].push_back(u);g[node].push_back(v);
	}
	dfs(node,0);
	for(int i=1;(1<<i)<=cnt;i++)
		for(int j=1;j+(1<<i)-1<=cnt;j++)
			st[j][i]=dep[st[j][i-1]]<dep[st[j+(1<<i-1)][i-1]]?st[j][i-1]:st[j+(1<<i-1)][i-1];
}
int lca(int u,int v)
{
	int l=min(dfn[u],dfn[v]),r=max(dfn[u],dfn[v]),k=log2(r-l+1);
	return dep[st[l][k]]<dep[st[r-(1<<k)+1][k]]?st[l][k]:st[r-(1<<k)+1][k];
}
int main()
{
	scanf("%d %d",&n,&m);
	for(int i=1;i<=m;i++)
		scanf("%d %d %d",&e[i].u,&e[i].v,&e[i].w);
	kruskal();
	int Q,ans=0;ull a1,a2;
	scanf("%d %llu %llu",&Q,&a1,&a2);
	for(int i=1;i<=Q;i++)
	{
		pair<int,int> q=myRanq(a1,a2,n);
		ans^=val[lca(q.first,q.second)];
	}
	printf("%d",ans);
}

上一题