【知识小结】圆方树 && 广义圆方树

本文总结了仙人掌结构的相关知识,包括仙人掌同构的概念,如环上的翻转和旋转同构,以及在解决实际问题中的应用。探讨了求仙人掌最大权独立集的40分钟圆方树DP解法,强调了易错点。此外,还介绍了在bzoj 2125题中使用圆方树解决最短路问题的策略,特别提到了处理环长的方法和在圆方树上求LCA的注意事项。
摘要由CSDN通过智能技术生成

关于仙人掌的总结

immortalCO的博客
yyb的博客
模板
namespace T{
   
	vector <int> e[maxn * 2];
	int tag[maxn * 2];
	void adde(int x,int y){
     //cout<<x<<" "<<y<<endl; 
		e[x].PB(y) , e[y].PB(x); }
}
namespace G{
   
	node e[maxn * 2];
	int head[maxn],cnt,dfn[maxn],fa[maxn],dfstime,used[maxn];

	void adde(int x,int y){
   
	//	if ( x < y ) cout<<x<<" "<<y<<endl;
		e[++cnt].to = y;
		e[cnt].next = head[x];
		head[x] = cnt;
	}
	void dfs(int x){
   
		dfn[x] = ++dfstime;
		for(int i = head[x] ; i ; i = e[i].next){
   
			if ( e[i].to == fa[x] ) continue;
			if ( dfn[e[i].to] ){
   
				if ( dfn[e[i].to] > dfn[x] ) continue;
				//find_circle
				++tot , T::tag[tot] = 1;
				int z = x;
				while ( z != e[i].to ){
   
					T::adde(tot,z);
					used[z] = 1;
					z = fa[z];
				}
				T::adde(e[i].to,tot);
			}
			else{
   
			 	fa[e[i].to] = x, dfs(e[i].to);
			 	if ( !used[e[i].to] ) used[e[i].to] = 1 , T::adde(x,e[i].to);
			}
		}
	}
}

例题

仙人掌同构

po姐题解
注意环上点是有序的,而树上子树无序。
环有翻转同构,环为根的话还有旋转同构

代码是NEERC 13 C
数据范围大一点

//仙人掌同构数
#include<bits/stdc++.h>
using namespace std;
#define PB push_back
#define lowbit(x) (x&(-x))
#define MP make_pair
#define fi first
#define se second
#define ls(x) (x << 1)
#define rs(x) ((x << 1) | 1)
#define rep(i,l,r) for (register int i = l ; i <= r ; i++)
#define down(i,r,l) for (register int i = r ; i >= l ; i--)
#define fore(i,x) for (int i = head[x] ; i ; i = e[i].next)
#define SZ(v) (int)v.size()

typedef long long ll;
typedef pair <int,int> pr;
const int maxn = 1e6 + 10;
const int inf = 1e8;

const ll MOD = 180143985094819841ll;
//const ll MOD = 1e9 + 7;
const ll C1 = 35224111;
const ll C2 = 33352437;
const ll C3 = 70525121; 

ll mul_C2[maxn],inv_C2[maxn];
int prime[maxn],cnt,tag[maxn],mn_p[maxn];

ll mul(ll a,ll b){
   
//	return a * b % MOD;
    return (a * b - (ll)(a / (long double)MOD * b + 1e-3)* MOD + MOD) % MOD;
//	return (__int128)a * b % MOD;
}
ll power(ll x,ll y){
   
    ll res = 1;
    while ( y ) {
   
        if ( y & 1 ) res = mul(res,x);
        x = mul(x,x);
        y >>= 1;
    }
    return res;
}
void init(){
   
	ll inv = power(C2,MOD - 2);
	mul_C2[0] = inv_C2[0] = 1;
	for (int i = 1 ; i < maxn ; i++){
   
		mul_C2[i] = mul(mul_C2[i - 1],C2);
		inv_C2[i] = mul(inv_C2[i - 1],inv);
	}
	for (int i = 2 ; i < maxn ; i++){
   
		if ( !tag[i] ) prime[++cnt] = i , mn_p[i] = i;
		for (int j = 1 ; j <= cnt && prime[j] * i < maxn ; j++){
   
			tag[i * prime[j]] = 1;
			mn_p[i * prime[j]] = prime[j];
			if ( i % prime[j] == 0 ) break;
		}
	}
}

map <int,int> ans; 
int tot,n,m;

struct node{
   
	int next,to,w;
};
void add_to_ans(int num){
   
	
	while ( num > 1 ){
   
		int c = 0 , cp = mn_p[num];
		while ( num % cp == 0 ) num /= cp , c++;
		ans[cp] += c;
	}
}
namespace T{
   
	vector <int> e[maxn * 2];
	int mx[maxn * 2],sz[maxn * 2],tag[maxn * 2];
	pr id[2] = {
   {
   inf,0},{
   inf,0}};

	void adde(int x,int y){
     //cout<<x<<" "<<y<<endl; 
		e[x].PB(y) , e[y].PB(x); }
	void find_g(int x,int fa){
   
		sz[x] = 1;
		for (auto y : e[x]){
   
			if ( y == fa ) continue;
			find_g(y,x);
			sz[x] += sz[y];
			mx[x] = max(mx[x],sz[y]);
		}
	}
	ll get_hash_tree(vector <ll> &vec){
   
		ll res = 1240198;
		for (auto x : vec){
   
			res = (res + power(C1,x)) % MOD;
		}
		return res;
	}
	ll get_hash_cyc(vector <ll> &vec){
   
		ll res = 3982003; ll q = 1;
		for (auto x : vec){
   
			q = mul(q,C2);
			res = (res + mul(q,power(C3,x))) % MOD;
		}
		return res;
	}
	vector <ll> all_cycles(vector <ll> &vec){
   
		vector <ll> item(SZ(vec) * 2);
		for (int i = 0 ; i < SZ(vec) ; i++){
   
			item[i] = mul(mul_C2[i + 1],power
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值