CF869D 翻

my

[[dfs]] [[Base Ring Tree]]

link

At first, I felt confused about the description.

calculate the number of simple paths in a completed binary tree with a few extra edges? n<1e9!?

O(n) is unacceptable.

Then, I tried to compress the nodes. But after I compressed them, I have way to calculate the number of simple paths.

I've read the tutorial.

How to compress a tree with only a few extra edges?

With one extra edge? 基环树。
What about more edge? 多环树?Name isn't important.
Find out the graph consisting of cycles.
Every node can represent the tree below it, so the small tree is able to be compressed to the root.

At last, calculate the number of simple paths is a simple dfs problem.

CODE

#include<bits/stdc++.h>
using namespace std;
const int N=500,M=2000,mod=1e9+7;
int n,m,h[N],nxt[M],to[M],t,a,b;
void add(int u,int v){
	nxt[++t]=h[u],h[u]=t,to[t]=v;
	nxt[++t]=h[v],h[v]=t,to[t]=u;
}
int it;
map<int,int>I;
int vis[N];
#define pb push_back
int d,rem;
int cal(int u){
	int l,r,_=0;
	for(it=u;it;_++,it>>=1);
	for(it=u;(it<<1|1)<=n;it=it<<1|1);r=it;
	for(it=u;(it<<1)<=n;it=it<<1);l=it;
	if(r>n-rem)return (1<<d-_+1)-1;
	else if(l<=n-rem)return (1<<d-_)-1;
	else return (1<<d-_)+n-l;
}
int num[N];
long long tot,ans;
void dfs(int u){
	vis[u]=1;tot+=num[u];
	for(int e=h[u],v;e;e=nxt[e])
		if(!vis[v=to[e]])dfs(v);
	vis[u]=0;
}
int x[5],y[5],u,v;
int id(int num){
	if(!I[num])I[num]=I.size();
	return I[num];
}
int fa;
int main(){
	scanf("%d%d",&n,&m);
	if(m==0){
		printf("%lld",1ll*n*n%mod);
		return 0;
	}
	for(it=n;it;it>>=1)d++;
	rem=n-(1<<d-1)+1;
	for(int i=0;i<m;i++){
		scanf("%d%d",&x[i],&y[i]);
		for(it=x[i];it;it>>=1)id(it);
		for(it=y[i];it;it>>=1)id(it);
	}
	for(auto p:I)if(p.first!=1)add(p.second,I[p.first>>1]);
	for(auto p:I)num[p.second]=cal(p.first);
	for(auto p:I){
		fa=I[p.first>>1];
		for(int e=h[u=p.second];e;e=nxt[e])
			if(!vis[v=to[e]]&&v!=fa)
				num[u]-=num[v],vis[v]=1;
	}
	memset(vis,0,sizeof vis);
	for(int i=0;i<m;i++)add(I[x[i]],I[y[i]]);
	for(auto p:I){
		tot=0;dfs(p.second);
		ans=(ans+tot*num[p.second]%mod)%mod;
	}
	printf("%lld",ans);
}

2022.6.4UPD:
#include<bits/stdc++.h>
#define fi first
#define se second
using namespace std;
const int N=500,M=2000,mod=1e9+7;
int n,m,h[N],nxt[M],to[M],t,vis[N],_[N],num[N],x,y,u,fa,r,i;
long long tot,ans;
map<int,int>I;
void add(int u,int v){
	nxt[++t]=h[u],h[u]=t,to[t]=v;
	nxt[++t]=h[v],h[v]=t,to[t]=u;
}
int id(int x){
	for(r=x;x;x/=2)I[x]=I.size();
	return I[r];
}
int cal(int x){
	for(r=i=0;(x<<i)<=n;++i)
		r+=min((x+1)<<i,n+1)-(x<<i);
	return r;
}
void dfs(int u){
	vis[u]=1;tot+=num[u];
	for(int e=h[u];e;e=nxt[e])if(!vis[to[e]])dfs(to[e]);
	vis[u]=0;
}
int main(){
	cin>>n>>m;if(m==0)cout<<1ll*n*n%mod,exit(0);
	for(i=0;i<m;i++)cin>>x>>y,add(id(x),id(y));
	for(auto p:I){
		num[p.se]+=_[p.se]=cal(p.fi);
		if(p.fi!=1)add(u=p.se,fa=I[p.fi/2]),num[fa]-=_[u];
	}
	for(auto p:I)tot=0,dfs(p.se),(ans+=tot*num[p.se]%mod)%=mod;
	cout<<ans;
}
posted @ 2022-12-11 11:48  -WD-  阅读(74)  评论(0)    收藏  举报