最小生成树(优先队列)
最小生成树例题:
最小生成树Kruskal算法
Time Limit: 1000MS Memory Limit: 65536K
Total Submissions: 227 Accepted: 124
Description
某省调查城镇交通状况,得到现有城镇道路统计表,表中列出了连接两个城镇需要花费的代价。省政府“畅通工程”的目标是使全省任何两个城镇间都可以实现交通(但不一定有直接的道路相连,只要互相间接通过道路可达即可)。问最少花费多少代价就可以完成工程?
Input
输入包含多组数据,对于每组测试数据
第一行包含两个正整数N和M(0 <=N <=1000,0 < M < 5000),分别代表现有城镇的数目和已修建的道路的数目。城镇分别以1~N编号。
接下来是M行道路信息。每一行有三个整数A,B,X(0 < A,B <= N ,0 < X < 10000),表示可以在城镇A和城镇B之间建一条花费为X的双向道路。保证数据可以完成工程。
Output
对于每组数据,输出完成工程需要花费的最少代价。
Sample Input
3 4
1 2 3
2 1 4
1 3 1
2 3 2
Sample Output
3
#include<bits/stdc++.h>
using namespace std;
struct node{
int s,to,w; //s为起点,to为终点,w为边的权重。
bool operator <(const node&ths)const{ //重载结构体小于运算符
return w>ths.w;
}
};
int pre[1050]; //记录根节点
int find(int x){ //并查集
if(x!=pre[x])return pre[x]=find(pre[x]);
else return x;
}
int main(){
priority_queue<node> pq; //定义优先队列
int n,m,a,b,c,i;
while(scanf("%d %d",&n,&m)!=EOF){
while(!pq.empty())pq.pop(); //初始化优先队列
for(i=0;i<n;i++)pre[i]=i; //初始化pre数组
for(i=0;i<m;i++){
scanf("%d %d %d",&a,&b,&c);
pq.push(node{a,b,c});
}
int cnt=0,sum=0; //cnt记录道路数 ,sum记录花费
while(cnt!=n-1){ //最小生成树只有n-1条边
node x=pq.top();
pq.pop();
if(find(x.s)!=find(x.to)){ //至多只有一个点在树内,保证不成环
cnt++;
pre[find(x.s )]=find(x.to ); //把两个点并入树
sum+=x.w;
}
}
printf("%d\n",sum);
}
return 0;
}
最小生成树裸题:http://acm.zjnu.edu.cn/CLanguage/showproblem?problem_id=1408
最小生成树的变题:http://acm.zjnu.edu.cn/CLanguage/showproblem?problem_id=2217