描述
Bessie has been hired to build a cheap internet network among Farmer John’s N (2 <= N <= 1,000) barns that are conveniently numbered 1…N. FJ has already done some surveying, and found M (1 <= M <= 20,000) possible connection routes between pairs of barns. Each possible connection route has an associated cost C (1 <= C <= 100,000). Farmer John wants to spend the least amount on connecting the network; he doesn’t even want to pay Bessie.
Realizing Farmer John will not pay her, Bessie decides to do the worst job possible. She must decide on a set of connections to install so that (i) the total cost of these connections is as large as possible, (ii) all the barns are connected together (so that it is possible to reach any barn from any other barn via a path of installed connections), and (iii) so that there are no cycles among the connections (which Farmer John would easily be able to detect). Conditions (ii) and (iii) ensure that the final set of connections will look like a “tree”.
输入
-
Line 1: Two space-separated integers: N and M
-
Lines 2…M+1: Each line contains three space-separated integers A, B, and C that describe a connection route between barns A and B of cost C.
-
输出
-
Line 1: A single integer, containing the price of the most expensive tree connecting all the barns. If it is not possible to connect all the barns, output -1.
样例输入
5 8
1 2 3
1 3 7
2 3 10
2 4 4
2 5 8
3 4 6
3 5 2
4 5 17
样例输出
42
解题思路:
求最大生成树
①将所有节点的距离最大生成树的距离(d[i])为-1
②从节点1开始更新与其邻接的点中的d[i]值,
③选择与当前最大生成树中的节点连接的d[i]值最大的节点加入最大生成树中
④在选取邻接点中最大时采用优先队列,默认是大根堆,取第一个即为邻接点内最大。
⑤若最大生成树包含了所有节点,输出最大权值
⑥否则输出-1
Code:
#include<iostream>
#include<algorithm>
#include<vector>
#include<queue>
#include<numeric>
using namespace std;
using P=pair<int,int>;
int N,M;
struct T{
int to,w;//下一个节点 权值
};
vector<vector<T>>Edge;//存储边的信息及权值
priority_queue<P,vector<P>>Q;//优先队列 利用大根堆实现
vector<int>d;
vector<bool>used;//是否被使用过
int ans=0;//记录权值之和
void Prime(){
for(int i=0;i<=N;i++)//把所有节点到已有生成树的距离为-1
d[i]=-1;
d[1]=0;
Q.push({0,1});//把1结点加入 并且d[1]为0
while(!Q.empty()){
auto e=Q.top();//取出队头元素 根据大顶堆 第一个为最大的
Q.pop();//弹出队列
int x=e.second,w=e.first;
if(used[x])//若x被访问过 则继续弹出下一个进行访问
continue;
ans+=d[x];
used[x]=true;//标记为已访问
for(auto h:Edge[x]){
if(d[h.to]<h.w){//d值 比边权值小 则更新
d[h.to]=h.w;
Q.push({h.w,h.to});//放入优先队列中
}
}
}
}
int main(){
cin>>N>>M;//顶点数 边数
Edge.resize(N+1);//节点1~N
d.resize(N+1);
used.resize(N+1);
int x,y,w;
for(int i=1;i<=M;i++){//无向图
cin>>x>>y>>w;
Edge[x].push_back({y,w});
Edge[y].push_back({x,w});
}
Prime();
int flag=1;
for(int i=1;i<=N;i++)//判断是否连通
if(!used[i])
flag=0;
if(flag)
cout<<ans;//输出最大生成树的权值之和
else
cout<<-1;
return 0;
}