题意:即给你n-1个网线,让你去连接n个人,然后使得每个人都能相互连通,求最大开心值,Hij表示第一个人和第二个人相连的到的好感度
注意Hij和Hji相等,且i==j时,开心值为零,求最大生成树的值;
思路:prim(普拉姆算法),就是把从小到大排序改成从大到小排序就行;
#include<stdio.h>
#include<stdlib.h>#include<string.h>
struct node
{
int left,right;
int value;
}re[100005];
int comp(const void *a ,const void *b)
{
return ((node *)a)->value>((node *)b)->value?-1:1; //注意:从大到小排序
}
int mark[10005];
int main()
{
int n,i,j,sum,count,number,t;
while(scanf("%d",&n)!=EOF)
{
count=0;
for(i=0;i<n;i++)
{
for(j=0;j<n;j++)
{
scanf("%d",&t);
if(j<=i)continue; //注意:hij和Hji的值相同,且i==j时为0;故可以减枝;
re[count].value=t;
re[count].left=i;
re[count++].right=j;
}
}
memset(mark,0,sizeof(mark));
qsort(re,count,sizeof(re[0]),comp);
number=0;
sum=0;
sum+=re[0].value;
mark[re[0].left]=1; //因为刚才是都被其他点相连,所以直接可用
mark[re[0].right]=1;
number+=2;
while(number!=n)
{
for(i=0;i<count;i++)
{
if(mark[re[i].left]+mark[re[i].right]==1) //只有当两个相连的点中,必须有且只能一个已经和其他点相连了
{
mark[re[i].left]=1;
mark[re[i].right]=1;
sum+=re[i].value;
number++;
if(number==n)break;
i=0; //注意:这部不能少,防止漏掉较适合的值
}
}
}
printf("%d\n",sum);
}
}