Kruskal and Prime and bellman-ford(附并查集)

Kruskal

struct Edge
{
    int s,e;///s记录起点,e记录终点
    double dis;///dis记录起点到终点的距离
}e[5555];
int cmp(Edge a,Edge b)
{
    return a.dis < b.dis;///按距离从小到大排列
}
int father(int x)///找父亲节点,用于判断是否在一个集合中
{
    if(x == fa[x]) return x;
    else
    {
        int root = father(fa[x]);
        fa[x] = root;
        return root;
    }
}
int Kruskal()
{
    for(int i = 1; i <= n; i++)
        fa[i] = i;
    sort(e,e+cunt,cmp);///按从小到大对所有边进行排序
    double ans = 0;
    for(int i = 0; i < cunt; i++)///遍历所有的边
    {
        int a = father(e[i].s);
        int b = father(e[i].e);
        if(a != b)
        {
            ans += e[i].dis;
            fa[a] = b;///合并集合
        }
    }
    return ans;///返回最小生成树的权值和
}
 

Prime

int Prime(int v)///最小生成树的起点v
{
    sum = 0;
    for(int i = 1; i <= n; i++)
        d[i] = dis[v][i];
    d[v] = 0;
    flag[v] = 1;///flag用来标记是否遍历过
    for(int i = 1; i < n; i++)///一共n个点,要找n-1条边
    {
        int minn = INF,k;
        for(int j = 1; j <= n; j++)///在所有u∈U,w∈V-U的边(u,w)∈E中找到一条权值最小的边
        {
            if(minn > d[j] && flag[j] == 0)
            {
                k = j;
                minn = d[j];
            }
        }
        flag[k] = 1;///将此点加入最小生成树中
        sum += d[k];
        for(int j =1; j <= n; j++)///更新不在最小生成树的点的边权值,以便找到下一个权值最小的边
        {
            if(flag[j] == 0 && d[j] > dis[k][j])
                d[j] = dis[k][j];
        }
    }
    return sum;///返回生成的最小生成树的权值和
}
 

Bellman-ford

int N, M;
typedef struct node
{
    int u, v;
    int cost;
} E;
node E[N];
int dis[N], pre[N];
bool Bellman()
{
    int ok;
    for(int i = 1; i <= N; ++i)
        dis[i] = (i == 1 ? 0 : MAX);
    for(int i = 1; i <= N - 1; ++i)
    {
        ok=1;
        for(int j = 1; j <= M; ++j)
            if(dis[E[j].v] > dis[E[j].u] + E[j].cost)
            {
                dis[E[j].v] = dis[E[j].u] + E[j].cost;
                ok=0;
            }
        if(ok==1)
            break;
    }
    bool flag = 1;
    for(int i = 1; i <= M; ++i)
        if(dis[E[i].v] > dis[E[i].u] + E[i].cost)
        {
            flag = 0;
            break;
        }
    return flag;
}
int main()
{
    cin>>N>>M;
    for(int i = 1; i <= M; ++i)
        cin>>E[i].u>>E[i].v>>E[i].cost;
    if(Bellman())
        cout<<dis[M];
    else
        cout<<"存在负";
    return 0;
}

并查集

int father(int x)///找父亲节点,用于判断是否在一个集合中
{
    if(x == fa[x]) return x;
    else  return fa[x]= father(fa[x]);
}
 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值