COGS——T2084. Asm.Def的基本算法
http://cogs.pro/cogs/problem/problem.php?pid=2084
★☆ 输入文件:asm_algo.in
输出文件:asm_algo.out
简单对比
时间限制:1 s 内存限制:256 MB
【题目描述】
“有句美国俗语说,如果走起来像鸭子,叫起来像鸭子,那就是一只鸭子。”斯科特·华莱士看着Asm.Def面前屏幕上滚动的绿色字符,若有所思地说。
“什么意思?”
“你的数据。看上去是一棵树。”
“按照保密条令,我什么也不说这是最好的——但见你这么热情,一句话不说也不好。”Asm.Def停下手中的快速数论变换,“确实是树。”
“然后你怎么算出来目标的位置?”
“都需要按照基本算法,按照图论的那一套理论,去产生。听说过LCA吗?不是那个印度飞机,我是说最近公共祖先……”
Asm.Def通过分析无线电信号得到了一棵有n个节点,以1为根的树。除1之外,节点i的父亲是p_i。节点带有权值,节点i的权值是w_i。
我们定义某点的祖先为从根到它路径上的所有点(包括它本身),而两个节点a、b的最近公共祖先是某个点p,使得p同时是a、b的祖先,而且p离根最远。
Asm.Def想要求出
(文字:∑∑w_i*w_j*w_LCA(i,j)),
其中LCA(i,j)是i、j的最近公共祖先,他认为这个值至关重要。由于这个值可能很大,Asm.Def只需要知道它模1,000,000,007(即10^9+7)的结果。
【输入格式】
第1行两个整数:n和w_1.
第2行到第n行,第i行有两个整数p_i和w_i。
【输出格式】
一行一个整数,即答案模1,000,000,007的值。
【样例输入】
2 2 1 1
【样例输出】
17
【提示】
1×1×1+1×2×2+2×1×2+2×2×2=17。
对于30%的数据,n<=100,w_i<=10。
对于60%的数据,n<=1000,w_i<=1000.
对于100%的数据,1<=n<=10^5,0<=w_i<=10^9,1<=p_i<i.
裸LCA只能拿60分后面就超时了
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include <algorithm> 2 #include <cstdio> 3 4 #define mod 1000000007 5 6 using namespace std; 7 8 const int N(1e6+15); 9 int n,x,ans,w[N],a[N]; 10 11 int sumedge,head[N]; 12 struct Edge 13 { 14 int from,to,next; 15 Edge(int from=0,int to=0,int next=0):from(from),to(to),next(next){} 16 }edge[N]; 17 void ins(int from,int to) 18 { 19 edge[++sumedge]=Edge(from,to,head[from]); 20 head[from]=sumedge; 21 } 22 23 int deep[N],size[N],dad[N],top[N]; 24 void DFS(int x) 25 { 26 deep[x]=deep[dad[x]]+1;size[x]=1; 27 for(int i=head[x];i;i=edge[i].next) 28 { 29 int to=edge[i].to; 30 if(dad[x]!=to) 31 dad[to]=x,DFS(to),size[x]+=size[to]; 32 } 33 } 34 void DFS_(int x) 35 { 36 int t=0;if(!top[x]) top[x]=x; 37 for(int i=head[x];i;i=edge[i].next) 38 { 39 int to=edge[i].to; 40 if(dad[x]!=to&&size[t]<size[to]) t=to; 41 } 42 if(t) top[t]=top[x],DFS_(t); 43 for(int i=head[x];i;i=edge[i].next) 44 { 45 int to=edge[i].to; 46 if(dad[x]!=to&&t!=to) DFS_(to); 47 } 48 } 49 50 int LCA(int x,int y) 51 { 52 for(;top[x]!=top[y];x=dad[top[x]]) 53 if(deep[top[x]]<deep[top[y]]) swap(x,y); 54 return deep[x]>deep[y]?y:x; 55 } 56 57 int main() 58 { 59 freopen("asm_algo.in","r",stdin); 60 freopen("asm_algo.out","w",stdout); 61 scanf("%d%d",&n,&w[1]); 62 for(int i=2;i<=n;i++) 63 scanf("%d%d",&x,w+i),ins(i,x),ins(x,i); 64 DFS(1); DFS_(1); 65 for(int i=1;i<=n;i++) 66 for(int j=1;j<=n;j++) 67 ans=(ans%mod+(w[i]*w[j]*w[LCA(i,j)])%mod)%mod; 68 printf("%d",ans); 69 return 0; 70 }
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include <algorithm> 2 #include <cstdio> 3 4 #define mod 1000000007 5 #define LL long long 6 7 using namespace std; 8 9 const LL N(1e5+15); 10 LL n,x,w[N]; 11 12 LL sumedge,head[N]; 13 struct Edge 14 { 15 LL from,to,next; 16 Edge(LL from=0,LL to=0,LL next=0):from(from),to(to),next(next){} 17 }edge[N]; 18 void ins(LL from,LL to) 19 { 20 edge[++sumedge]=Edge(from,to,head[from]); 21 head[from]=sumedge; 22 } 23 24 LL sum[N],dad[N],ans; 25 void DFS(LL x) 26 { 27 sum[x]=w[x]; 28 for(LL i=head[x];i;i=edge[i].next) 29 { 30 LL to=edge[i].to; 31 if(!dad[to]) 32 { 33 dad[to]=x; DFS(to); 34 ans=(ans%mod+sum[x]%mod*sum[to]%mod*w[x]%mod)%mod; 35 sum[x]=(sum[x]%mod+sum[to]%mod)%mod; 36 } 37 } 38 } 39 40 int main() 41 { 42 freopen("asm_algo.in","r",stdin); 43 freopen("asm_algo.out","w",stdout); 44 scanf("%lld%lld",&n,&w[1]); 45 for(LL i=2;i<=n;i++) 46 scanf("%lld%lld",&x,w+i), ins(x,i); 47 DFS(1); ans=ans%mod*2%mod; 48 for(LL i=1;i<=n;i++) 49 ans=(ans%mod+w[i]%mod*w[i]%mod*w[i]%mod)%mod; 50 printf("%lld",ans%mod); 51 return 0; 52 }