H. Sugar Sweet II

  • 单向边森林不能通过dfs找环
  • 抽象的题目需要通过模拟样例理解题意
  • 列表模拟样例
  • 链式前向星双倍空间(边&边的访问函数)
点击查看代码
#include <bits/stdc++.h>
using namespace std;
const int mod=1000000007;
long long a[500005],b[500005],w[500005],c[500005],p[500005],cnt[500005];
long long h[500005],ne[1000005],t[1000005],tot,m,n;
bool v[500005],f[1000005];
long long jc[500005],jcinv[500005];
vector<long long>g[500005];
long long read1()
{
	char cc=getchar();
	while(!(cc>=48&&cc<=57))
	{
		if(cc=='-')
		{
			break;
		}
		cc=getchar();
	}
	bool f=false;
	long long s=0;
	if(cc=='-')
	{
		f=true;
	}
	else
	{
		s=cc-48;
	}
	while(1)
	{
		cc=getchar();
		if(cc>=48&&cc<=57)
		{
			s=s*10+cc-48;
		}
		else
		{
			break;
		}
	}
	if(f==true)
	{
		s=-s;
	}
	return s;
}
long long power(long long n,long long p)
{
	if(p==0)
	{
		return 1;
	}
	else if(p==1)
	{
		return n%mod;
	}
	else if(p%2==0)
	{
		long long tmp=power(n,p/2);
		return tmp*tmp%mod;
	}
	else
	{
		long long tmp=power(n,p/2);
		return tmp*tmp%mod*n%mod;
	}
}
void add(long long u,long long v)
{
	tot++;
	ne[tot]=h[u];
	h[u]=tot;
	t[tot]=v;
}
long long dfs1(long long n1)
{
	v[n1]=true;
	bool pd=false;
	for(long long i=h[n1];i;i=ne[i])
	{
		if(f[i]==false)
		{
			f[i]=true;
			if(i>n)
			{
				f[i-n]=true;
			}
			else
			{
				f[i+n]=true;
			}
			long long w=t[i];
			if(v[w]==false)
			{
				long long tmp=dfs1(w);
				if(tmp>0)
				{
					pd=true;
				}
			}
			else
			{
				m++;
				c[w]=m;
				g[m].push_back(w);
				pd=true;
			}
		}
	}
	if(pd==true)
	{
		if(c[n1]==0)
		{
			g[m].push_back(n1);
			return c[n1]=m;
		}
		else
		{
			return 0;
		}
	}
	return 0;
}
void dfs2(long long n1)
{
	v[n1]=true;
	for(long long i=h[n1];i;i=ne[i])
	{
		long long w=t[i];
		if(i<=n&&v[w]==false)
		{
			if(p[w]==-1)
			{
				if(p[n1]==0)
				{
					p[w]=0;
					cnt[w]=0;
				}
				else
				{
					cnt[w]=cnt[n1]+1;
					p[w]=jcinv[cnt[w]];
				}
			}
			dfs2(w);
		}
	}
}
void pre()
{
	jc[0]=1;
	jcinv[0]=1;
	for(long long i=1;i<=500000;i++)
	{
		jc[i]=jc[i-1]*i%mod;
	}
	jcinv[500000]=power(jc[500000],1000000005);
	for(long long i=500000;i>1;i--)
	{
		jcinv[i-1]=jcinv[i]*i%mod;
	}
}
int main()
{
//	freopen("H.in","r",stdin);
//	freopen("H.out","w",stdout);
	pre();
	long long T;
	cin>>T;
	while(T--)
	{
		n=read1();
		for(long long i=1;i<=n;i++)
		{
			a[i]=read1();
			p[i]=-1;
			cnt[i]=0;
		}
		for(long long i=1;i<=n;i++)
		{
			b[i]=read1();
			add(b[i],i);
		}
		for(long long i=1;i<=n;i++)
		{
			add(i,b[i]);
		}
		for(long long i=1;i<=n;i++)
		{
			w[i]=read1();
		}
		for(long long i=1;i<=n;i++)
		{
			if(a[i]<a[b[i]])
			{
				p[i]=1;
				cnt[i]=1;
			}
			else if(a[i]>=a[b[i]]+w[b[i]])
			{
				p[i]=0;
				cnt[i]=0;
			}
		}
		for(long long i=1;i<=n;i++)
		{
			if(!v[i])
			{
				long long tmp=dfs1(i);
			}
		}
		for(long long i=1;i<=n;i++)
		{
			v[i]=false;
		}
		for(long long i=1;i<=m;i++)
		{
			long long x=-1;
			for(long long j=0;j<g[i].size();j++)
			{
				if(p[g[i][j]]!=-1)
				{
					x=g[i][j];
				}
			}
			if(x==-1)
			{
				for(long long j=0;j<g[i].size();j++)
				{
					p[g[i][j]]=0;
					cnt[g[i][j]]=0;
				}
				x=g[i][0];
			}
			dfs2(x);
		}
		for(long long i=1;i<n;i++)
		{
			printf("%lld ",(a[i]+p[i]*w[i]%mod)%mod);
		}
		printf("%lld\n",(a[n]+p[n]*w[n]%mod)%mod);
		for(long long i=1;i<=tot;i++)
		{
			f[i]=false;
		}
		tot=0;
		for(long long i=1;i<=n;i++)
		{
			v[i]=false;
			h[i]=0;
			c[i]=0;
		}
		for(long long i=1;i<=m;i++)
		{
			g[i].clear();
		}
		m=0;
	}
	return 0;
}
posted @ 2024-02-02 19:55  D06  阅读(78)  评论(0编辑  收藏  举报