【NOIP2013模擬11.6A組】靈能矩陣(pylon)
阿新 • • 發佈:2018-12-22
時間有保證,空間也不大(第一頁第一個)
好了,說回正題
一看樣例,感覺好像就是個裸的dfs,但在打程式碼的時候發現有毒。。。
比如說一個非葉子節點i,如果它要散逸能量的話一定要散逸son[i]的倍數,那樣的話:
這個資料:
10
0 0 0 3 3 3 2 2 2 2
1 2
1 3
2 4
2 5
2 6
3 7
3 8
3 9
3 10
我們可以發現這題的正確答案應該是0
所以gg了,重新想(努力思考中。。。)
考場想著用堆來解決此問題,但發現不但T掉還會WA o(╥﹏╥)o,表示無奈。
經過研究發現,對於一個非葉子節點x,它的所有兒子節點都要小於等於它的最小的那個兒子節點。
然後,我們需要找出一個m——也就是每個兒子是值。因為要滿足它的兒子節點相同且符合,那麼我們可以設一個l[x]表示x的兒子的lcm。l[x]=lcm(son[x])*x的兒子個數。那麼m=mi-mi mod (l[x]/兒子的個數)。
上標:
#include<cstdio>
#include<algorithm>
#define ll long long
using namespace std;
struct node{int v,fr;}e[200010];
int n,tail[100010],son[100010],cnt=0,top=0;
ll ans=0,a[100010],l[100010];
inline int read()
{
int x=0; char c=getchar();
while (c<'0' || c>'9') c=getchar();
while (c>='0' && c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
return x;
}
void add(int u,int v) {e[++cnt]=(node){v,tail[u]}; tail[u]=cnt;}
ll gcd(ll x,ll y) {return !y ? x:gcd(y,x%y);}
void dfs(int x,int fa)
{
l[x]=1;if (!son[x]) return;
ll mi=(ll)(1<<30)*(1<<30),s=0;
for (int p=tail[x] ,v;p;p=e[p].fr)
if ((v=e[p].v)!=fa)
{
dfs(v,x);s+=a[v];
l[x]=l[x]*l[v]/gcd(l[x],l[v]);
mi=min(mi,a[v]);
}
a[x]=(mi-mi%l[x])*son[x];
l[x]*=son[x];ans+=s-a[x];
}
int main()
{
freopen("pylon.in","r",stdin);
freopen("pylon.out","w",stdout);
n=read();
for (int i=1;i<=n;i++) a[i]=read(),son[i]=-1;
for (int i=1,u,v;i<n;i++)
u=read(),v=read(),add(u,v),add(v,u),son[u]++,son[v]++;
son[1]++;dfs(1,0);
printf("%lld\n",ans);
return 0;
}