/*
这题也很难过
n个点,m条边,选择任意几条边使得总花费<=k,而且和1相连的点的权值和最大
枚举组成最小生成树的点
总共2^16种选择,对每种选择求最小生成树,如果最小生成树的值<=k,选择点权值和最大的
*/
#include <bits/stdc++.h>
#define INF 0x3f3f3f3f
using namespace std;
int Map[25][25],f[25],Max,vis[25],dis[25],n,sum,kk;
void choose(int x){
sum=0;
kk=0;
int i=1;
while(x){
if(x&1){
sum+=f[i];
vis[i]=0;
kk++;
}
x>>=1;
i++;
}
}
int prim(int x){
memset(vis,1,sizeof(vis));
memset(dis,INF,sizeof(dis));
choose(x);
int ans=0;
dis[1]=0;
for(int i=1;i<=kk;i++){
int index=-1,Min=INF;
for(int j=1;j<=n;j++){
if(!vis[j]&&Min>dis[j]){
Min=dis[index=j];
}
}
if(index==-1)
return -1;
vis[index]=1;
ans+=dis[index];
for(int j=1;j<=n;j++){
if(!vis[j]&&dis[j]>Map[index][j])
dis[j]=Map[index][j];
}
}
return ans;
}
int main()
{
int t,m,k,u,v,w;
scanf("%d",&t);
while(t--){
Max=-1;
memset(Map,INF,sizeof(Map));
scanf("%d%d%d",&n,&m,&k);
for(int i=1;i<=n;i++)
scanf("%d",&f[i]);
while(m--){
scanf("%d%d%d",&u,&v,&w);
if(Map[u][v]>w)
Map[u][v]=Map[v][u]=w;
}
for(int i=1;i<(1<<n);i++){
if(i%2==0)
continue;
int ans=prim(i);
if(ans!=-1&&ans<=k){
Max=max(Max,sum);
}
}
printf("%d\n",Max);
}
return 0;
}
【最小生成树】UVA_12507
最新推荐文章于 2022-02-09 21:32:53 发布