CDOJ 1966 Kruskal 解法
时间复杂度O(mlogm) m为边数,这里主要是边排序占时间,后面并查集还好
1 #include <cstdio> 2 #include <cstring> 3 #include <iostream> 4 #include <algorithm> 5 using namespace std; 6 typedef long long LL; 7 8 const int N=2002; 9 const int M=2e5+2; 10 int n,m,tot=0,num=0; 11 LL ans=0; 12 int f[N]; 13 struct Node 14 { 15 int u,v; 16 LL w; 17 bool operator < (const Node & b) 18 { 19 return w < b.w; 20 } 21 22 }G[M]; 23 24 int find(int x) 25 { 26 return x==f[x]?x:f[x]=find(f[x]); 27 } 28 29 int unite(int x,int y) 30 { 31 x=find(x); 32 y=find(y); 33 if(x!=y)f[x]=y; 34 } 35 36 void kruskal() 37 { 38 for(int i=1;i<=n;i++)f[i]=i; 39 sort(G,G+tot); 40 for(int i=0;i<tot;i++) 41 { 42 int u=find(G[i].u); 43 int v=find(G[i].v); 44 if(u!=v) 45 { 46 unite(u,v); 47 ans+=G[i].w; 48 num++; 49 } 50 } 51 if(num==n-1) 52 { 53 cout<<"yes"<<endl; 54 cout<<ans<<endl; 55 } 56 else 57 cout<<"no"<<endl; 58 } 59 60 int main() 61 { 62 63 cin>>n>>m; 64 65 while(m--) 66 { 67 int a,b,v,p; 68 cin>>a>>b>>v>>p; 69 if(p==0)continue; 70 G[tot].u=a; 71 G[tot].v=b; 72 G[tot].w=v; 73 tot++; 74 } 75 kruskal(); 76 return 0; 77 }
prim模板:主要用于稠密图,尤其是完全图的最小生成树
时间复杂度为O(n^2),如果用最小堆优化,为O(mlogn) [实际为O((m+n)logn),假设m边数>=n顶点数,从而简写] 算法分为两部分,一个找当前最小值,一个根据当前点的临边更新数组。logn获取最小值并从堆中删除,后用logn执行一条边的更新
1 int cost[N][N]; // 表示e=(u,v)的权值,不存在情况为INF 2 int mincost[N]; // 从集合x出发的边到每个顶点的最小权值 3 bool vis[N]; // 集合x内的顶点 4 int V; // 顶点数 5 6 int prim() 7 { 8 for(int i=0;i<V;i++) 9 { 10 mincost[i]=INF; 11 vis[i]=0; 12 } 13 mincost[0]=0; // 默认选第一个顶点为起始点 14 int res=0; 15 16 while(true) 17 { 18 int v=-1; 19 for(int u=0;u<V;u++) 20 if(!vis[u]&&(v==-1||mincost[u]<mincost[v]))v=u; 21 22 if(v==-1)break; 23 vis[v]=1; 24 res+=mincost[v]; 25 for(int u=0;u<V;u++) 26 { 27 if(mincost[u]>cost[v][u]) 28 mincost[u]=cost[v][u]; 29 } 30 } 31 return res; 32 }