题意:
有一幅双向图连接N个城市(标号1~n,1表示首都) 每个城市有一个价值W.
地震摧毁了所有道路,现给出可修复的m条道路并给出修复每条道路所需的费用
问在总费用不超过k的情况下,使得 与 首都连通的所有城市 的价值和 最大
解题思路:
点的数量不超过16 ,2^16次方枚举所有城市是否在连通的集合类
再通过prim判断这个集合是否合法即可
坑的是输入路径时可能会出现同样的点多次输出,要取最小的那个
#include <iostream>
#include <algorithm>
#include <string.h>
#define imax 1005
using namespacestd;
int n,m,k,maxn;
int po[20],map[20][20];
int pi[20];
int lowcost[20],s[20],u;
int prim()
{
int sum=0,polu=0;
for(int j=1;j<=n;j++)
lowcost[j]=map[1][j];
memset(s,0,sizeof(s));
s[1]=1;
for(int i=1;i<=n;i++)
{
int minn=imax;
for(int j=1;j<=n;j++)
{
if(s[j]==0&&minn>lowcost[j]&&pi[j]==1)
{
minn=lowcost[j];
u=j;
}
}
if(minn==imax)
break;
s[u]=1;
polu+=po[u];
sum=sum+lowcost[u];
for(int j=1;j<=n;j++)
{
if(lowcost[j]>map[u][j]&&pi[j]==1)
lowcost[j]=map[u][j];
}
}
if(sum<=k)
return polu;
else
return -1;
}
void pai(int ans,int kk,int d)
{
if(ans>kk)
{
int polu=prim();
if(polu!=-1)
maxn=max(maxn,polu);
return;
}
for(int i=2;i<=n;i++)
{
if(i>d)
{
pi[i]=1;
pai(ans+1,kk,i);
pi[i]=0;
}
}
}
int main()
{
int t,u,v,c;
cin>>t;
while(t--)
{
scanf("%d %d %d",&n,&m,&k);
for(int i=1;i<=n;i++)
scanf("%d",&po[i]);
memset(map,0x3f,sizeof(map));
for(int i=0;i<m;i++)
{
scanf("%d %d %d",&u,&v,&c);
if(c<map[u][v])
map[u][v]=map[v][u]=c;
}
memset(pi,0,sizeof(pi));
pi[1]=1;
maxn=0;
for(int kk=2;kk<=n;kk++)
{
pai(2,kk,1);
//printf("********\n");
}
cout<<maxn+po[1]<<endl;
}
return0;
}
前男友联系了我,这几天有点心神不定
曾经的大男孩现在心事有点重,我不知道他喜不喜欢现在的生活,感觉有些疲惫的样子
他已经有了未婚妻,想来要是我在他身边,恐怕也不能让他变得轻松,因为我没有办法在他身边安稳地陪着他
希望他身边的那个人可以给他带来他真正想要的生活