求补充我的代码
查看原帖
求补充我的代码
250699
mot1ve楼主2020/8/28 12:13

就是我的自定义函数里的dfs,怎么实现把这棵树(我转化成了有向图)填成一个小根堆的所有方案数算出来。

//并查集+树转有向图
//x连y的树的根节点之下就是find[y]->x连一条边
//先把图建对了再说
//暴搜看能出现几个小根堆,小根堆性质,每个点的权值都不小于父亲的权值 
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int mod=1e9+7;
int ans,size,n,q;
int fa[100010],head[100010];
bool vis[100010];
struct node{
	int nxt,to;
}edge[100010];
int idx;
void add(int u,int v)//u向v连边 
{
	edge[++idx].nxt=head[u];
	edge[idx].to=v;
	head[u]=idx;
}
int find(int x)//并查集找根 
{
	if(x==fa[x]) return x;
	return fa[x]=find(fa[x]);
}
void get(int x)//获得这棵树的节点个数,从x(根节点)出发. 
{
	for(int i=head[x];i;i=edge[i].nxt)
	{
		int v=edge[i].to;
		size++;
		get(v);
	}
}
void dfs(int u,int last,int cnt)//u表示当前的点,last表示它的父节点的值,cnt表示填了几个数了,选的数必须比他父节点的大,满足小根堆的性质。 
{
	if(cnt==size)//填满了 
	{
		ans++;
		return ;
	}
	for(int i=head[u];i;i=edge[i].nxt)
	{
		
	}
}
int main()
{
	//freopen("heap.in","r",stdin);
    //freopen("heap.out","w",stdout);
	cin>>n>>q;
	for(int i=0;i<=n-1;i++)//初始化并查集,编号是0到n-1 
	{
		fa[i]=i;
	}
	for(int i=1;i<=q;i++)
	{
		int op,x,y;
		scanf("%d",&op); 
		if(op==1)//把真正的x的根接在y的根下面。 
		{
			scanf("%d%d",&x,&y);
			x=(x+ans)%n;//真正的x 
		    y=(y+ans)%n;//真正的y
			y=find(y);//y所在树的根 
			x=find(x);//x所在树的根 
			add(y,x);//树上连边
			fa[x]=y;
			size=1;
			get(y);
			//cout<<y<<" "<<size<<endl;
		}
		else if(op==2)//op==2的时候记录ans,下一次op==1的时候要用 
		{
			scanf("%d",&x);
			x=(x+ans)%n;//真正的x
			x=find(x);//x所在树的根
			size=1;//自己这个点也算
			ans=0;//每次ans要重置 
			get(x);//找出x所在树的节点数;
			vis[0]=1;
			dfs(x,0,1);//从根开始填数,根节点必须填0。 
			printf("%d\n",ans); 
		}
	}
	return 0;
} 
2020/8/28 12:13
加载中...