这种题目很不擅长,接下来要多加训练
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <string>
#include <cstring>
#include <cmath>
#include <vector>
#include <list>
#include <map>
#include <set>
#include <deque>
#include <queue>
#include <stack>
#include <bitset>
#include <functional>
#include <sstream>
#include <iomanip>
#include <cmath>
#include <cstdlib>
#include <ctime>
#pragma comment(linker, "/STACK:102400000,102400000")
typedef long long ll;
#define INF 1e9
#define MAXN 10000
#define MAXM 100
const int maxn = 100005;
const int mod = 1000003;
#define eps 1e-6
#define pi 3.1415926535897932384626433
#define rep(i,n) for(int i=0;i<n;i++)
#define rep1(i,n) for(int i=1;i<=n;i++)
#define scan(n) scanf("%d",&n)
#define scanll(n) scanf("%I64d",&n)
#define scan2(n,m) scanf("%d%d",&n,&m)
#define scans(s) scanf("%s",s);
#define ini(a) memset(a,0,sizeof(a))
#define out(n) printf("%d\n",n)
//ll gcd(ll a,ll b) { return b==0?a:gcd(b,a%b);}
using namespace std;
vector<int> G[maxn];
int h[mod+10]; //记录积为i的重心
int pro[maxn]; // 记录当前到i号点的积
int vex[mod+10]; // 记录积为i的点
int inv[mod+10]; //记录i的逆
int id[maxn]; //记录该次dfs产生的点和积
int ans[2]; //记录当前答案
int son[maxn]; //记录以i当前为根的结点个数
int wroot,wval;//当前重心编号,以及以邻居为根的最大点数的最小值(描述有点乱,详细的看代码
bool vis[maxn]; //描述是否访问过该节点(只有重心才会被标记)
int val[maxn];
int cnt;
int n, K;
void init()
{
ini(vis);
ini(son);
ans[0] = ans[1] = INF;
ini(h);
}
void getRoot(int u,int fa) //求u所在“连通块”的重心,一遍dfs,复杂度O(N)
{
son[u] = 1;
int mxv = 0;
for(int i = 0;i < G[u].size(); i++)
{
int v = G[u][i];
if(vis[v] || v == fa) continue;
getRoot(v,u);
son[u] += son[v];
mxv = max(mxv, son[v]);
}
mxv = max(mxv,son[0] - son[u]);
if(wval > mxv)
{
wroot = u;
wval = mxv;
}
}
void dfs(int u,int fa,int Prep)
{
int tmp = pro[cnt] = (ll)Prep * val[u] % mod; //一直wa在这,一定要加tmp,若放dfs(pro[cnt-1])会出错
id[cnt++] = u;
son[u] = 1;
for(int i = 0;i < G[u].size(); i++)
{
int v = G[u][i];
if(vis[v] || v == fa) continue;
dfs(v,u,tmp);
son[u] += son[v];
}
}
void update(int a,int b)
{
if(a > b) swap(a,b);
if(a < ans[0]) ans[0] = a, ans[1] = b;
else if(a == ans[0] && b < ans[1]) ans[1] = b;
}
void solve(int u,int all)
{
//cout<<u<<' '<<all<<endl;
if(all == 1) return;
son[0] = all;
wval = INF;
getRoot(u,-1);
u = wroot;
// cout<<u<<endl;
for(int i = 0;i < G[u].size(); i++)
{
int v = G[u][i];
if(vis[v] || v == u) continue;
cnt = 0;
dfs(v,u,val[u]);
rep(i,cnt)
{
// cout<<pro[i]<<endl;
if(pro[i] == K) update(u,id[i]);
int x = (ll)pro[i] * inv[val[u]] % mod; //这条链的积
int y = (ll)K * inv[x] % mod; // K/x部分
if(h[y] == u)
{
update(id[i],vex[y]);
}
}
rep(i,cnt) //将一条条链的积保存下来
{
if(h[pro[i]] == u)
{
vex[pro[i]] = min(id[i],vex[pro[i]]);
}
else
{
h[pro[i]] = u;
vex[pro[i]] = id[i];
}
}
}
vis[u] = 1; //标记u
for(int i = 0;i < G[u].size(); i++)
{
int v = G[u][i];
if(vis[v] || v == u) continue;
solve(v,son[v]);
}
}
ll ext_gcd(ll a,ll b,ll &x,ll &y)
{
if(b==0)
{
x=1;y=0;
return a;
}
ll d=ext_gcd(b,a%b,y,x);
y-=a/b*x;
return d;
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("in.txt","r",stdin);
// freopen("out.txt","w",stdout);
#endif
ll x,y;
for(int i=0;i<mod;++i)
{
ext_gcd(i,mod,x,y);
x%=mod;
if(x<0) x+=mod;
inv[i]=x;
}
while(~scanf("%d%d",&n,&K))
{
init();
rep1(i,n){
scanf("%d",&val[i]);
G[i].clear();
}
int x,y;
rep(i,n-1)
{
scan2(x,y);
G[x].push_back(y);
G[y].push_back(x);
}
solve(1,n);
if(ans[0] == INF) puts("No solution");
else printf("%d %d\n",ans[0],ans[1]);
}
return 0;
}