- 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;
}