#include<cstdio>
#include<cstring>
#define _rep(i,a,b) for(int i=(a);i<=(b);i++)
#define _for(i,a,b) for(int i=(a);i<(b);i++)
typedef long long ll;
int q,n,m;
int s[15];
int base[20000][15];
int v[15];
int g[15][15];
int dp[15][15][1<<13];//dp[i][j][S]表示当前在i点,且前一个点在j点并且走过了集合S中的所有点一次对应的当前最小sum值
ll num[15][15][1<<13];//num[i][j][S]表示当前在i点,前一个点是j且走过了集合S中的所有点时,并在sum取最小值时,这些走过的点有多少种排列符合之前的要求
int main()
{
//freopen("in.txt","r",stdin);
scanf("%d",&q);
_rep(i,0,13)s[i]=1<<i;
memset(base,0,sizeof(base));
_for(i,0,s[13])//计算base[x][i]=1表示x的二进制第i位是1
{
int tmp=i,p=0;
while(tmp)base[i][p++]=tmp%2,tmp>>=1;
}
while(q--)
{
scanf("%d%d",&n,&m);
_for(i,0,n)scanf("%d",&v[i]);
memset(g,0,sizeof(g));
_for(i,0,m)
{
int u,v;
scanf("%d%d",&u,&v);
g[u-1][v-1]=g[v-1][u-1]=1;
}
if(n==1)
{
printf("%d 1\n",v[0]);continue;
}
memset(dp,-1,sizeof(dp));
memset(num,0,sizeof(num));
_for(i,0,n)_for(j,0,n)if(i!=j&&g[i][j])
{
dp[i][j][s[i]+s[j]]=v[i]+v[j]+v[i]*v[j];
num[i][j][s[i]+s[j]]=1;
}
_for(S,0,s[n])_for(i,0,n)if(base[S][i]==1)//集合S有节点i
_for(j,0,n)if(i!=j&&base[S][j]==1&&g[i][j])//集合S有节点j且i到j有边
{
if(dp[i][j][S]==-1)continue;
_for(k,0,n)if(base[S][k]==0&&g[k][i])//集合S中没有k且i到k有边
{
if(dp[k][i][S+s[k]]<dp[i][j][S]+v[k]+v[k]*v[i]+g[k][j]*v[k]*v[i]*v[j])//新的最大值
{
dp[k][i][S+s[k]]=dp[i][j][S]+v[k]+v[k]*v[i]+g[k][j]*v[k]*v[i]*v[j];
num[k][i][S+s[k]]=num[i][j][S];
}
else if(dp[k][i][S+s[k]]==dp[i][j][S]+v[k]+v[k]*v[i]+g[k][j]*v[k]*v[i]*v[j])//相同最大值
num[k][i][S+s[k]]+=num[i][j][S];
}
}
ll sum=0;int maxn=0;
_for(i,0,n)_for(j,0,n)if(i!=j&&g[i][j])
{
if(maxn<dp[i][j][(1<<n)-1])
maxn=dp[i][j][(1<<n)-1],sum=num[i][j][(1<<n)-1];
else if(maxn==dp[i][j][(1<<n)-1])
sum+=num[i][j][(1<<n)-1];
}
printf("%d %lld\n",maxn,sum/2);
}
return 0;
}
“`