1,Kueskal(加边)
就是一个并查集的应用吧
先把所有的边按从小到大排序,然后再按顺序判断每一条边要不要加上,就是边两边的点已经是一个集合(就是说,已经有可以联通的路了)就不用再加了,还不是就加
代码
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
using namespace std;
const int maxn = 1000000 + 10;
int fa[maxn];
struct edge{
int u;
int v;
int len;
}e[maxn];
bool cmp(edge a, edge b){
return a.len < b.len;
}
int init(){
for(int i = 0; i < maxn; i++){
fa[i] = i;
}
}
/*int tofind(int x){
int an = x;
if(an == fa[an]) return an;
return fa[an] = tofind(an);
}*/
int tofind(int x){
int an = x;
while(fa[an] != an){
an = fa[an];
}//找根节点
int t = x;
while(fa[x] != an){
x = fa[x];
fa[t] = an;
t = x;
}//缩短路径
return an;
}
int tojoin(int a, int b){
a = tofind(a);
b = tofind(b);
if(a != b){
fa[a] = b;
return 1;
}
return 0;
}//合并
int main(){
int n;
while(cin>>n){
for(int i = 0; i < n; i++){
scanf("%d%d%d",e[i].u, e[i].v, e[i].len);
}
sort(e, e + n, cmp);
int sum = 0;
for(int i = 0; i < n; i++){
sum += e[i].len*tojoin(e[i].u, e[i].v);
}
printf("%d",sum);
}
return 0;
}
2.Prim(加点)
从第一个点开始,找这一点连着的所有的边里最短的,然后再从这个边连着的那个点开始遍历(如果有环的话只能用这个方法)
代码(鹏哥的代码/[无辜])
#include<queue>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int maxn = 20000 + 10;
int cnt = 0;
struct edge{
int v;
int len;
int nex;
bool operator <(const edge &a) const{
return len > a.len;//重载运算符,有点酷
}
}e[maxn];
int id[maxn];
bool used[maxn];
void add(int from, int to, int len){
e[cnt].v = to;
e[cnt].len = len;
e[cnt].nex = id[from];
id[from] = cnt++;
}//链式前向星
void init(int n){
cnt = 0;
for(int i = 0; i < n; i++){
id[i] = -1;
}
memset(e, 0, sizeof(e));
memset(used, 0, sizeof(used));
}
int Prime(int x, int n){
int tot = 1;
int TT = 0;
int sum = 0;
priority_queue<edge> q;//因为重载了运算符所以这里的优先队列是从小到大排的
for(;tot < n;)
{
used[x] = 1;//标记点
for(int i = id[x]; ~i; i = e[i].nex){
if(used[e[i].v])
continue;
q.push(e[i]);
}
while(!q.empty()){
edge mye = q.top();
q.pop();
if(used[mye.v])
continue;
else{
sum += mye.len;
x = mye.v;
tot++;
break;
}
}
}
while(!q.empty()){q.pop();}
return sum;
}
int main(){
int n, m;
while(scanf("%d %d", &m, &n), m){
int a, b, c;
init(n);
for(int i = 0; i < m; i++){
scanf("%d%d%d", &a, &b, &c);
add(a, b, c);
add(b, a, c);
}
//for(int i=0;i<cnt;i++)
// cout<<e[i].len<<' '<<e[i].nex<<' '<<e[i].v<<endl;
//for(int i=1;i<=14;i++)
// cout<<id[i]<<' ';
//cout<<endl;
int ans = Prime(1, n);
printf("%d\n", ans);
}
return 0;
}