COGS——T2084. Asm.Def的基本算法
★☆ 輸入文件: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分後面就超時了
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 }AAAAAATTTT
容易發現每個點自身的值都會加上,剩下的可以用記憶化搜索求出來
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 }AAAAAAAAAA
COGS——T2084. Asm.Def的基本算法