最小瓶颈路(加强版)

  • 众所周知,树(或森林)有很好的性质,并且容易通过很多常见数据结构维护。而一般图则没有那么好的性质,所幸有时我们可以把一般图上的某些问题转化到树上考虑。
  • kruskal重构树就是这样的一种方法。通过点边转化,它将边权体现在点上,得到了一棵恰有 n 个叶子的二叉树
//Kruskal重构树(最小瓶颈路)
//Tarjan离线(近似)线性求LCA 
#include <bits/stdc++.h>
using namespace std;
const int mod=1000000007;
int A,B,C,P;
inline int rnd(){return A=(A*B+C)%P;}
vector<int>a[140005],g[140005];
int fa[140005],id[140005],val[140005],tot;
struct l1
{
	int u,v,w;
}l[100005];
bool cmp(l1 a,l1 b)
{
	return a.w<b.w;
}
int get(int x)
{
	if(fa[x]==x)
	{
		return x;
	}
	return fa[x]=get(fa[x]);
}
int ans;
void tarjan(int n1,int Fa)
{
	id[n1]=1;
	for(int i=0;i<a[n1].size();i++)
	{
		tarjan(a[n1][i],n1);
	}
	for(int i=0;i<g[n1].size();i++)
	{
		if(id[g[n1][i]]==2)
		{
			ans=(ans+val[get(g[n1][i])])%mod;
		}
	}
	fa[n1]=get(Fa);
	id[n1]=2;
}
int main()
{
	ios::sync_with_stdio(false);
	cin.tie(0);
	int n,m,q;
	cin>>n>>m;
	for(int i=1;i<2*n;i++)
	{
		fa[i]=i;
	}
	for(int i=1;i<=m;i++)
	{
		cin>>l[i].u>>l[i].v>>l[i].w;
	}
	sort(l+1,l+m+1,cmp);
	tot=n;
	for(int i=1;i<=m;i++)
	{
		if(get(l[i].u)!=get(l[i].v))
		{
			tot++;
			val[tot]=l[i].w;
			a[tot].push_back(get(l[i].u));
			fa[get(l[i].u)]=tot;
			a[tot].push_back(get(l[i].v));
			fa[get(l[i].v)]=tot;
		}
	}
	cin>>q;
	cin>>A>>B>>C>>P;
	for(int i=1;i<=tot;i++)
	{
		fa[i]=i;
	}
	for(int i=1;i<=q;i++)
	{
		int u=rnd()%n+1,v=rnd()%n+1;
		g[u].push_back(v);
		g[v].push_back(u);
	}
	tarjan(tot,0);
	cout<<ans<<endl;
	return 0;
}
posted @ 2025-02-19 08:36  D06  阅读(22)  评论(0)    收藏  举报
//雪花飘落效果