您的位置:首页 > 其它

最大生成树Bad Cowtractors

2022-04-29 20:18 726 查看

题目链接:http://poj.org/problem?id=2377;

 

 仔细阅读题目,你会发现一个词-" as large as possible",这个词的意思是尽可能最大; 

来,我们翻译一下题目:

题目大意是

现在有一个人给人修建一些线路,(当然,我们想要少花钱消费,人家就想多多赚你的钱了,现在就给出这么一个问题)。让你求修得所有电路能赚取的最大利润,若电路不能被全部修完,输出“-1”.

那这个题考的是最小生成树的题,但是按照题目要求,我们要改成所谓的最大生成树问题,

即求得生成树的权值是最大的而不是最小的,那该怎么办呢?

其实也很好处理,最小生成树的核心无非是按照边的权值最小逐一将图的权值一一加进生成树里,

那对于这个题来说,就将边的权值最大一一加进树里即可,

所以说,和最小生成树相比,核心就在这:

 

bool cmp(edge a,edge b)
{
return a.w>b.w;
}

将原来的按小排序改成按大排序即可。

还有几个点需要注意的是,这个题的依旧是要判断图的联通性,如果联通则输出生成树的权值,如果不连通这次输出-1;

然后根据最小生成树进行改动即可;

Talk is cheap. Show me the code.

#include<iostream>//poj头文件很烦银
#include<algorithm>
#include<stdio.h>
#include<cmath>
#include<queue>
#include<cstring>
#include<vector>
#include<map>
using namespace std;
const int num=1e5+10;
struct edge
{
int u;
int v;
int w;
}e[num];//存图
int s[num];//集合
int n,m;
int ans;//生成树权值
int cnt;//统计边数
bool cmp(edge a,edge b)//降序排列
{
return a.w>b.w;
}
int find_set(int x)//集合查找+路径压缩
{
if(x!=s[x])
s[x]=find_set(s[x]);
return s[x];
}
void kruskal()
{
for(int i=1;i<=n;i++)//集合初始化
s[i]=i;
sort(e+1,e+1+m,cmp);
for(int i=1;i<=m;i++)
{
int b=find_set(e[i].u);
int c=find_set(e[i].v);
if(b==c)//如果重边则跳过
continue;
s[c]=b;//合并集合
ans+=e[i].w;//累计权值
cnt++;//边+1
if(cnt==n-1)//联通至此结束
break;
}
}
int main()
{
cin>>n>>m;
for(int i=1;i<=m;i++)
{
scanf("%d %d %d",&e[i].u,&e[i].v,&e[i].w);
}
kruskal();
if(cnt==n-1)
printf("%d\n",ans);
else//不连通输出-1
printf("%d\n",-1);
return 0;
}

 

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: