- 1小时出头独立做出来一道紫色打星题,开心!其实你还是有点厉害的呀~
 
- 考虑图的最小生成树是答案的上界,要想让答案更小只有让图不连通,先预处理出每个连通块的答案,再通过动态规划转移出答案
 
#include <bits/stdc++.h>
using namespace std;
int a[20],s[1<<16],val[1<<16],f[1<<16];
int fa[20];
struct e1
{
	int u,v,w;
}e[405];
bool cmp(e1 a,e1 b)
{
	return a.w<b.w;
}
int get(int x)
{
	if(fa[x]==x)
	{
		return x;
	}
	return fa[x]=get(fa[x]);
}
int main()
{
	ios::sync_with_stdio(false);
	cin.tie(0);
	int n,m;
	cin>>n>>m;
	for(int i=0;i<n;i++)
	{
		cin>>a[i];
	}
	for(int i=1;i<=m;i++)
	{
		cin>>e[i].u>>e[i].v>>e[i].w;
	}
	sort(e+1,e+m+1,cmp);
	for(int i=1;i<(1<<n);i++)
	{
		val[i]=-1;
		int p=__builtin_ctz(i);
		s[i]=a[p]+s[i-(1<<p)];
		if(s[i]==0)
		{
			val[i]=0;
			for(int j=0;j<n;j++)
			{
				fa[j]=j;
			}
			int edge=0;
			for(int j=1;j<=m;j++)
			{
				int u,v;
				u=e[j].u;
				v=e[j].v;
				if(((i>>u)&1)&&((i>>v)&1))
				{
					if(get(u)!=get(v))
					{
						fa[get(u)]=get(v);
						val[i]+=e[j].w;
						edge++;
					}
				}
			}
			if(edge+1!=__builtin_popcount(i))
			{
				val[i]=-1;
			}
		}
	}
	for(int i=1;i<(1<<n);i++)
	{
		f[i]=-1;
		for(int j=i;j;j=(j-1)&i)
		{
			int k=(i&(~j));
			if(val[j]!=-1&&f[k]!=-1)
			{
				if(f[i]==-1)
				{
					f[i]=val[j]+f[k];
				}
				else
				{
					f[i]=min(f[i],val[j]+f[k]);
				}
			}
		}
	}
	if(f[(1<<n)-1]==-1)
	{
		cout<<"Impossible"<<endl;
	}
	else
	{
		cout<<f[(1<<n)-1]<<endl;
	}
	return 0;
}