1. 程式人生 > >【NOIP2013模擬11.6A組】靈能矩陣(pylon)

【NOIP2013模擬11.6A組】靈能矩陣(pylon)

在這裡插入圖片描述
時間有保證,空間也不大(第一頁第一個)
好了,說回正題
一看樣例,感覺好像就是個裸的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; }