最小生成树学习总结(二)
解决最小生成树的算法有两个:
1.Prim(普里姆算法)算法
2.Krustral(克鲁斯卡尔算法)
两个算法的比较:
1.Kruskal:
(1).将所有边从小到大加入,在此过程中判断是否构成回路
(2).使用数据结构:并查集(不会并查集点我)
(3).时间复杂度:O(ElogE)
(4).适用于稀疏图
2.Prim:
(1).从任一节点出发,不断扩展
(2).使用数据结构:堆
(3).时间复杂度:O(ElogV) 或 O(VlogV+E)(斐波那契堆)
(4).适用于密集图
(5).若不用堆则时间复杂度为O(V2 )
我们还是用题目直接看吧:洛谷3366
题目描述:
如题,给出一个无向图,求出最小生成树,如果该图不连通,则输出orz。
输入格式: 第一行包含两个整数N、M,表示该图共有N个结点和M条无向边。(N<=5000,M<=200000)
接下来M行每行包含三个整数Xi、Yi、Zi,表示有一条长度为Zi的无向边连接结点Xi、Yi
输出格式:
输出包含一个数,即最小生成树的各边的长度之和;如果该图不连通则输出orz
输入样例:
4 5
1 2 2
1 3 2
1 4 3
2 3 4
3 4 3输出样例:
7
#include<iostream>//最小生成树(普利姆算法)
#include<cstdio>
#include<cstring>
#include<stack>
#include<queue>
#include<set>
#include<map>
#include<vector>
#include<list>
#include<cmath>
#include<algorithm>
#define lson node<<1,st,mid
#define rson node<<1|1,mid+1,ed
#define mem(a,x) memset(a,x,sizeof(a))
#define me(a) memset(a,0,sizeof(a))
#define IOS ios::sync_with_stdio(false)
#define lowbit(x) x&(-x)
typedef long long ll;
const ll mod=1e9+7;
const ll INF=0x3f3f3f3f;
const ll maxn=1e6+5;
const double pi = acos(-1.0);
using namespace std;
int n,m;
struct code{
int to;
int w;
int next;
}edge[maxn<<1];
int head[maxn],dist[maxn];
bool vis[maxn];
int cnt;
void intn(){
cnt=0;
mem(head,-1);
mem(vis,false);
mem(dist,INF);
}
void add(int u,int v,int w){
cnt++;
edge[cnt].to=v;
edge[cnt].w=w;
edge[cnt].next=head[u];
head[u]=cnt;
}
int ans=0;
int prim(int u){
int tot=0,k=u;
for(int i=head[u];i!=-1;i=edge[i].next){
dist[edge[i].to]=min(dist[edge[i].to],edge[i].w);
}
dist[k]=0;
vis [k]=true;
while(++tot<n){
int minn=INF;
vis[k]=true;
for(int i=1;i<=n;i++){
if(!vis[i]&&minn>dist[i]){
minn=dist[i];
k=i;
}
}
ans+=minn;
for(int i=head[k];i!=-1;i=edge[i].next){
int v=edge[i].to;
if(dist[v]>edge[i].w&&!vis[v]){
dist[v]=edge[i].w;
}
}
}
return ans;
}
int main(){
IOS;
cin>>n>>m;
intn();
while(m--){
int u,v,w;
cin>>u>>v>>w;
add(u,v,w);add(v,u,w);
}
int res=prim(1);
bool flag=false;
for(int i=1;i<=n;i++){
if(dist[i]>=INF){
cout<<"orz"<<endl;
flag=true;
}
}
if(!flag) cout<<res<<endl;
}
#include<iostream>//最小生成树(克鲁斯卡尔算法)
#include<cstdio>
#include<cstring>
#include<stack>
#include<queue>
#include<set>
#include<map>
#include<vector>
#include<list>
#include<cmath>
#include<algorithm>
#define lson node<<1,st,mid
#define rson node<<1|1,mid+1,ed
#define mem(a,x) memset(a,x,sizeof(a))
#define me(a) memset(a,0,sizeof(a))
#define IOS ios::sync_with_stdio(false)
#define lowbit(x) x&(-x)
typedef long long ll;
const ll mod=1e9+7;
const ll INF=0x3f3f3f3f;
const ll maxn=1e6+5;
const double pi = acos(-1.0);
using namespace std;
struct code{
int u,v,w;
}edge[maxn<<1];
int n,cnt,m;
int F[maxn];
void intn(){
cnt=0;
mem(F,-1);
}
int find(int x){
if(F[x]==-1) return x;
else return F[x]=find(F[x]);
}
bool cmp(code a,code b){
return a.w<b.w;
}
int Kruskal(){
int ans=0,bs=0;
sort(edge,edge+cnt,cmp);
for(int i=0;i<cnt;i++){
int u=edge[i].u;
int v=edge[i].v;
int w=edge[i].w;
int t1=find(u);
int t2=find(v);
if(t1!=t2){
ans+=w;
F[t1]=t2;
bs++;
}
if(bs==n-1) break;
}
if(bs<n-1) return -1;
else return ans;
}
void add(int u,int v,int w){
cnt++;
edge[cnt].v=v;
edge[cnt].w=w;
edge[cnt].u=u;
}
int main(){
IOS;
intn();
cin>>n>>m;
while(m--){
int u,v,w;
cin>>u>>v>>w;
add(u,v,w);add(v,u,w);
}
int x=Kruskal();
if(x==-1) cout<<"orz"<<endl;
else cout<<x<<endl;
}

浙公网安备 33010602011771号