2017.9.9 图论 — 最小生成树

来源:互联网 发布:c语言中预处理命令 编辑:程序博客网 时间:2024/06/09 23:59

Kruskal: 按照边的权值的顺序从小到大查一遍,若不产生圈(重边等),则把当前边加入生成树中。
O(|E|log|V|)

#include<iostream>#include<cstdio>#include<algorithm>using namespace std;int n,m;int fa[10005];struct bian{    int f,t,d;}e[10005];int cmp(bian a,bian b){    return a.d<b.d;}int find(int x) {    if(fa[x]==x) return x;    else return fa[x]=find(fa[x]);//写法2:return fa[x] == x?x:fa[x] = find(fa[x]); }int kru()//通过并查集 {     int ans=0;    sort(e+1,e+m+1,cmp);    for(int i=1;i<=n;i++) fa[i]=i;    for(int i=1;i<=m;i++)    {        int fx=e[i].f , fy=e[i].t;        if(find(fx)!=find(fy)) // ← 能将目前边加上的条件:不在同一个连通分量里         //判环:若有环,则环中的点一定一个fa,即在同一个集合中,则这条边不会加入         //两个点已经加入过了,所以fa一定出相同,若再加上这条边,就会使这两点之间可以相互到达的路径有两条,也就是说形成了回路        {            fa[find(fx)]=find(fy);            ans+=e[i].d;        }    }    return ans;}int main(){    scanf("%d%d",&n,&m);    for(int i=1;i<=m;i++)    cin>>e[i].f>>e[i].t>>e[i].d;    printf("%d\n",kru());    return 0;}

Prim:

int cost[max_v][max_v];//边e=(u,v)的权值(不存在的情况下设为INF) int mincost[max_v];    //从集合x出发的边到每个顶点的最小权值 bool used[max_v];      //顶点i是否包含在集合x中 int V;                 //顶点数 int prim() {       for(int i=0;i<v;i++)    {        mincost[i] = INF;        used[i] = false;     }    mincost[0] = 0;    int res = 0;    while(true)    {        int v=-1;        //从不属于x的顶点中选取从x到其权值最小的顶点         for(int u,int u<v;int u++)        {            if(!used[u] && (v == -1 || mincost[v]<mincost[v]))            v = u;         }    }    if(v == -1) break;    used[v] = true;     //把顶点v加入x     res+ = mincost[v];  //把边的长度加到结果里     for(int u=0;u<v;u++)    {        mincost[u]=min(mincost[u],cost[v][u]);    }    return res;}