您的位置:首页 > 其它

图论算法之最小生成树

2016-04-07 21:35 435 查看
1.最小生成树(Prim算法)普里姆算法,一般针对的是无向图,而且其是连通的

#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
const int N=100;
const int MAX=100000;
bool visit
;
int d
,path
;
struct Node{
int v,w;//这里w代表权值
Node* next;
Node(int x,int y):v(x),w(y),next(0){}//参数初始化表
};
struct Graph{
int E,V;
Node* Adj
;//邻接表
};
//无向图
void CreateGraph(Graph &G){
cin>>G.V>>G.E;
for(int i=0;i<G.V;++i) //顶点数小于N
G.Adj[i]=NULL;
for(int i=0;i<G.E;++i){//边数
int u,v,w;
cin>>u>>v>>w;
Node* p=new Node(u,w);
p->next=G.Adj[v];
G.Adj[v]=p;
p=new Node(v,w);
p->next=G.Adj[u];
G.Adj[u]=p;//w代表边<u,v>的权值
}
}
int cmp(int x,int y){

return d[x]<d[y];//当此不等式成立时,x,y的排序是xy,否则为yx
}
int min(int x,int y){

return x>y?y:x;
}
int Prim(Graph &G, int s){
Node* p;
vector<int> q;
for(int i=0;i<G.V;++i){
visit[i]=false;
d[i]=MAX;
path[i]=-1;
q.push_back(i);
}
d[s]=0;
while(!q.empty()){
sort(q.begin(),q.end(),cmp);
int u=q[0];
visit[u]=true;
q.erase(q.begin());
for(p=G.Adj[u];p;p=p->next)
{
int v=p->v;
if(!visit[v]){
d[v]=min(d[v],p->w);
if(d[v]==p->w)
path[v]=u;
}
}
}
int result=0;
for(int i=0;i<G.V;++i){
result+=d[i];}
return result;
}
int main(){
Graph G;
CreateGraph(G);
cout<<Prim(G, 0);
return 0;
}
这里的排序准则cmp,是将元素按其d[ ]的从小到大排序。

2. 最小生成树(Kruskal 算法)克鲁斯卡尔算法

#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
const int n=12, m=7; //m是顶点数,n是边数
struct Edge{

int v,u,w;//这里w是边<v,u>的权重
//Edge(int x,int y,int z):v(x),u(y),w(z){}
};
int cmp(Edge x, Edge y){

return x.w<y.w;

}
int p[m];//并查集
void MakeSet(int x){
p[x]=-1;//各树的初始高度是-1,这里-1仅仅是个假设的初始值,不设为0,是因为顶点是0,...,m-1;

}
int Find(int x){
if(p[x]<=-1)
return x;
else
return Find(p[x]);

}
void Union(int x, int y){
p[x]=y;
if(p[x]<p[y]) //按高度合并
p[y]=x; //将以y为根的树合并在以x为根的树上
else{
if(p[x]==p[y])
p[y]--;
p[x]=y;

}

}
int Kruskal(Edge* e){//n为边数,m为顶点数
for(int i=0;i<m;++i)
MakeSet(i);
int result=0;
sort(e,e+n,cmp);
for(int i=0;i<n;++i){
if(Find(e[i].v)!=Find(e[i].u)){
Union(Find(e[i].v),Find(e[i].u));
cout<<e[i].v<<e[i].u<<e[i].w<<endl;
result+=e[i].w;
}

}

return result;
}
int main(){
int v,u,w;
Edge e
;
for(int i=0;i<n;++i){
cin>>v>>u>>w;
e[i].v=v;
e[i].u=u;
e[i].w=w;
}
cout<<Kruskal(e)<<endl;

return 0;
}


上述两种算法都是贪婪算法
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: