思路比较裸,但是要把答案存到哈希表里面,这里需要一定技巧,否则会被K=1且点权全是1的数据卡飞。预处理乘法逆元。TLE了一天。换了种点分治的姿势……
#pragma comment(linker,"/STACK:102400000,102400000") #include<cstdio> #include<algorithm> #include<cstring> using namespace std; int Res;char C; inline int Read() { Res=0;C='*'; while(C<'0'||C>'9')C=getchar(); while(C>='0'&&C<='9'){Res=Res*10+(C-'0');C=getchar();} return Res; } #define MAXN 100001 #define MOD 1000003 #define INF 2147483647 typedef long long ll; typedef pair<int,int> Point; typedef pair<ll,int> Point2; int n,K; Point ans; ll m,w[MAXN],inv[MOD]; int v[MAXN<<1],first[MAXN],next[MAXN<<1],en,id[MOD]; void AddEdge(const int &U,const int &V) { v[++en]=V; next[en]=first[U]; first[U]=en; } bool centroid[MAXN]; int size[MAXN]; int calc_sizes(int U,int Fa) { int res=1; for(int i=first[U];i;i=next[i]) if(v[i]!=Fa&&(!centroid[v[i]])) res+=calc_sizes(v[i],U); return size[U]=res; } Point calc_centroid(int U,int Fa,int nn) { Point res=make_pair(INF,-1); int sum=1,maxv=0; for(int i=first[U];i;i=next[i]) if(v[i]!=Fa&&(!centroid[v[i]])) { res=min(res,calc_centroid(v[i],U,nn)); maxv=max(maxv,size[v[i]]); sum+=size[v[i]]; } maxv=max(maxv,nn-sum); res=min(res,make_pair(maxv,U)); return res; } int En,last; Point2 dis[MAXN]; void calc_dis(int root,int U,int Fa,ll d) { dis[En++]=make_pair(d,U); for(int i=first[U];i;i=next[i]) if(v[i]!=Fa&&(!centroid[v[i]])) calc_dis(root,v[i],U,d*w[v[i]]%MOD); } void calc_pairs(int s) { for(int i=last;i<En;++i) { ll t=m*inv[dis[i].first*w[s]%MOD]%MOD; if(id[t]) ans=min(ans,dis[i].second<id[t]? make_pair(dis[i].second,id[t]): make_pair(id[t],dis[i].second)); } for(int i=last;i<En;++i) { if(id[dis[i].first]) id[dis[i].first]=min(id[dis[i].first],dis[i].second); else id[dis[i].first]=dis[i].second; } } void solve(int U) { calc_sizes(U,-1); int s=calc_centroid(U,-1,size[U]).second; centroid[s]=1; for(int i=first[s];i;i=next[i]) if(!centroid[v[i]]) solve(v[i]); En=0; dis[En++]=make_pair(1,s); id[1]=s; for(int i=first[s];i;i=next[i]) if(!centroid[v[i]]) { last=En; calc_dis(v[i],v[i],s,w[v[i]]); calc_pairs(s); } for(int i=0;i<En;++i) id[dis[i].first]=0; centroid[s]=0; } void init() { memset(first,0,(n+1)*sizeof(int)); en=0; ans=make_pair(INF,INF); } int main() { inv[1]=1; for(int i=2;i<MOD;i++) { int a=MOD/i,b=MOD%i; inv[i]=(inv[b]*(-a)%MOD+MOD)%MOD; } int a,b; while(scanf("%d%I64d",&n,&m)!=EOF) { init(); for(int i=1;i<=n;++i) { w[i]=(ll)Read(); w[i]%=MOD; } for(int i=1;i<n;++i) { a=Read(); b=Read(); AddEdge(a,b); AddEdge(b,a); } solve(1); if(ans==make_pair(INF,INF)) puts("No solution"); else printf("%d %d ",ans.first,ans.second); } return 0; }