HDU 4812 D Tree (樹上點分治),hdu4812
題目地址:HDU 4812
這題是13年南京地區賽的現場題。
樹分治思想。
樹分治的過程中記錄下每個子樹的所有到達根的路徑的積,用best記錄下每個積的最小端點,然後再枚舉當前子樹的每個積,然後用逆元的方法求出當積為k時所需要的另一個端點值,並更新答案。
代碼如下:
#include <iostream>#include <string.h>#include <math.h>#include <queue>#include <algorithm>#include <stdlib.h>#include <map>#include <set>#include <stdio.h>#include <time.h>using namespace std;#define LL __int64#define pi acos(-1.0)#pragma comment(linker, "/STACK:1024000000")const int mod=1e6+3;const int INF=0x3f3f3f3f;const double eqs=1e-9;const int MAXN=100000+10;int head[MAXN], cnt, root, min1, ans1, ans2, tot, k, ff;int siz[MAXN], vis[MAXN], best[MAXN*10], flag[MAXN*10];LL Inv[MAXN*10], a[MAXN];struct N{ LL x; int num;}F[MAXN];struct node{ int v, next;}edge[MAXN<<1];void add(int u, int v){ edge[cnt].v=v; edge[cnt].next=head[u]; head[u]=cnt++;}void getroot(int u, int fa, int s){ int max1=0; for(int i=head[u];i!=-1;i=edge[i].next){ int v=edge[i].v; if(v==fa||vis[v]) continue ; getroot(v,u,s); max1=max(max1,siz[v]); } max1=max(max1,s-siz[u]); if(min1>max1){ min1=max1; root=u; }}void getsize(int u, int fa){ siz[u]=1; for(int i=head[u];i!=-1;i=edge[i].next){ int v=edge[i].v; if(v==fa||vis[v]) continue ; getsize(v,u); siz[u]+=siz[v]; }}LL ksm(LL x){ LL ans=1; int k=mod-2; while(k){ if(k&1) ans=ans*x%mod; k>>=1; x=x*x%mod; } return ans;}void getF(int u, int fa, LL val){ F[tot].x=val; F[tot++].num=u; for(int i=head[u];i!=-1;i=edge[i].next){ int v=edge[i].v; if(v==fa||vis[v]) continue ; getF(v,u,val*a[v]%mod); }}void work(int u){ vis[u]=1; int i, j; LL tmp; for(i=head[u];i!=-1;i=edge[i].next){ int v=edge[i].v; if(vis[v]) continue ; min1=INF; getsize(v,u); getroot(v,u,siz[v]); work(root); } ff++; best[1]=u; flag[1]=ff; for(i=head[u];i!=-1;i=edge[i].next){ int v=edge[i].v; if(vis[v]) continue; tot=0; getF(v,u,a[v]); for(j=0;j<tot;j++){ tmp=(LL)k*Inv[F[j].x*a[u]%mod]%mod; if(flag[tmp]!=ff) continue ; int minnum=min(best[tmp],F[j].num); int maxnum=max(best[tmp],F[j].num); if(ans1>minnum){ ans1=minnum; ans2=maxnum; } else if(ans1==minnum&&ans2>maxnum) ans2=maxnum; } for(j=0;j<tot;j++){ if(flag[F[j].x]!=ff||best[F[j].x]>F[j].num){ best[F[j].x]=F[j].num; flag[F[j].x]=ff; } } } vis[u]=0;}void init(){ memset(head,-1,sizeof(head)); cnt=0; memset(vis,0,sizeof(vis)); ans1=ans2=INF; memset(flag,-1,sizeof(flag));}void init1(){ Inv[0]=0; for(int i=1;i<mod;i++){ Inv[i]=ksm((LL)i); }}int main(){ int n, i, u, v; init1(); while(scanf("%d%d",&n,&k)!=EOF){ init(); ff=0; for(i=1;i<=n;i++){ scanf("%I64d",&a[i]); } for(i=1;i<n;i++){ scanf("%d%d",&u,&v); add(u,v); add(v,u); } min1=INF; getsize(1,-1); getroot(1,-1,n); work(root); if(ans1==INF) puts("No solution"); else printf("%d %d\n",ans1,ans2); } return 0;}
著作權聲明:本文為博主原創文章,未經博主允許不得轉載。