【BZOJ】3573: [Hnoi2014]米特运输

时间:2022-03-03 17:42:44

题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=3573


屁话一堆,就是说:

1.一棵树中的每个点的每个儿子的权值之和要等于这个点的权值

2.一棵树中的每个点的每个儿子的权值相等。

所以,考虑确定一个点即确定的整个树的每个点的权值,但是我们受限于数据范围又不能枚举每一个点,所以枚举每一个点,考虑这个点的权值不变的话根节点的权值会是多少,这个是可以DP的,然后取个众数即可。

当然,权值过大所以需要一发HASH。


 #include<iostream>
#include<cstdio>
#include<algorithm>
#include<vector>
#include<cstdlib>
#include<cmath>
#include<cstring>
using namespace std;
#define maxn 501000
#define llg long long
#define md1 1000000007
#define md2 1000000009
#define yyj(a) freopen(a".in","r",stdin),freopen(a".out","w",stdout);
llg n,m,du[maxn],ans,tail,val[maxn];
vector<llg>a[maxn];
struct node
{
llg v1,v2;
}dl[maxn]; bool cmp(const node a,const node&b) {if (a.v1==b.v1) return a.v2<b.v2;else return a.v1<b.v1;} void init()
{
cin>>n;
for (llg i=;i<=n;i++) scanf("%lld",&val[i]);
for (llg i=;i<n;i++)
{
llg x,y;
scanf("%lld%lld",&x,&y);
a[x].push_back(y); du[x]++;
}
} void dfs(llg x,llg fa,llg v1,llg v2)
{
llg w=a[x].size();
dl[++tail].v1=(v1*val[x])%md1;
dl[tail].v2=(v2*val[x])%md2;
v1*=du[x],v2*=du[x];
v1%=md1,v2%=md2;
for (llg i=;i<w;i++)
{
dfs(a[x][i],x,v1,v2);
}
} int main()
{
yyj("a");
init();
dfs(,,,);
sort(dl+,dl+tail+,cmp);
ans=n;
for (llg l=;l<=tail;l++)
{
llg r=l;
while (r+<=tail)
{
if (dl[l].v1!=dl[r+].v1 || dl[l].v2!=dl[r+].v2) break;
r++;
}
ans=min(ans,n-(r-l+));
}
cout<<ans;
return ;
}