Hdu1233

May 30, 2021


题链接: hdu-1223模版题

Ac代码:


#include<bits/stdc++.h>
using namespace std;

const int maxn=100;
int n,m;
int ans=0;

typedef struct
{
    int lowcost;
    int adjvex;
    //例如:shortEdge[2].adjvex=4,意思就是,当前这个点2与点4最近。
    //shortEdge[2].lowcost=6,意思是点2与当前最近点4直接的距离为6
}Element;

void Prim(int arc[maxn][maxn],int w)
{
    int i,j,k;
    int Min;
    Element shortEdge[n+1];
    for(i=1;i <= n;i++)
    {
        shortEdge[i].lowcost=arc[w][i];
        shortEdge[i].adjvex=w;
    }
    shortEdge[w].lowcost=0;
    for(i=1;i <= n-1;i++)//寻找最近点
    {
        Min=0x3f3f3f3f;
        for(j=1;j <= n;j++)
        {
            if((shortEdge[j].lowcost!=0)&&(shortEdge[j].lowcost < Min))//1.该点是否已经加入最小生成树的集合里;2.该点是否小于Min(即寻找最小距离的)
            {
                Min=shortEdge[j].lowcost;
                k=j;
            }
        }
        ans+=shortEdge[k].lowcost;
        shortEdge[k].lowcost=0;//将k的最小花费设置为0,这里相当于一个集(最小生成树中的点的集合U),也可以用一个数组来实现
        for(j=1;j<= n;j++)//更新操作
        {
            if(arc[k][j]< shortEdge[j].lowcost)
            {
                shortEdge[j].lowcost=arc[k][j];
                shortEdge[j].adjvex=k;
            }
        }
    }
}

int main()
{
    int arc[maxn][maxn];
    int a,b,c;
    //万事开头难,初始化时需根据题目的要求进行初始化
    while(cin>>n&&n)
    {
        ans=0;
        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<=n;j++)
            {
                if(i==j)arc[i][j]=0;
                else arc[i][j]=0x3f3f3f3f;
            }
        }
        m=n*(n-1)/2;

        for(int i=0;i<m;i++)
        {
            cin>>a>>b>>c;
            if(arc[a][b]>c)
            {
                arc[a][b]=c;
                arc[b][a]=c;
            }

        }
        Prim(arc,1);
        cout<<ans<<endl;
    }
    return 0;
}

#include <bits/stdc++.h>
using namespace std;

const int N = 510, INF = 0x3f3f3f3f;

int n, m;
int g[N][N];
int dist[N];
bool st[N];

int prim()
{
    memset(dist, 0x3f, sizeof dist);
    memset(st,false,sizeof st);
    int res = 0;
    for (int i = 0; i < n; i ++ )//这里是逆向的求最小生成树,如果有些题目要求从第一个节点开始,则可以把循环修改一下,这里的i=0的时候,就是进行初始化
    {
        int t = -1;
        for (int j = 1; j <= n; j ++ )
            //!st[j]表示的是这个点没有被用过
            //(t == -1 || dist[t] > dist[j])代表的是要么是第一次开始找(也就是t == -1,此时不存在dist[t] > dist[j])的情况,要么找到了一个点j,集合到点j的距离小于到t的距离,就更新t
            if (!st[j] && (t == -1 || dist[t] > dist[j]))
                t = j;

        if (i && dist[t] == INF) return INF;

        if (i) res += dist[t];
        st[t] = true;

        for (int j = 1; j <= n; j ++ ) dist[j] = min(dist[j], g[t][j]);
    }

    return res;
}


int main()
{
    while(cin>>n&&n)
    {
        if(n==0)break;
        memset(g, 0x3f, sizeof g);
        m=n*(n-1)/2;
        while (m -- )
        {
            int a, b, c;
            cin>>a>>b>>c;
            g[a][b] = g[b][a] = min(g[a][b], c);
        }
        int t = prim();
        cout<<t<<endl;
    }
    return 0;
}

#include <bits/stdc++.h>
using namespace std;

const int NUM=103;
int S[NUM];//并查集
struct Edge{//定义边
    int u,v,w;
}edge[NUM*NUM];

bool cmp(Edge a,Edge b){return a.w<b.w;}

int find(int u){return S[u]==u?u:find(S[u]);}//查询并查集,返回u的根节点

int n,m;

int kruskal()
{
    int ans=0;
    for(int i=1;i<=n;i++)S[i]=i;//初始化,开始时每个村庄都是单独的集
    sort(edge+1,edge+1+m,cmp);
    for(int i=1;i<=m;i++)
    {
        int b=find(edge[i].u);//边的前端点u属于哪个集
        int c=find(edge[i].v);//边的后端点v属于哪个集
        if(b==c)continue;//产生圈,丢弃这个边
        S[c]=b;//合并
        ans+=edge[i].w;//计算MST
    }
    return ans;
}

int main()
{
    while(cin>>n&&n)
    {
        m=n*(n-1)/2;
        for(int i=1;i<=m;i++)
        {
            cin>>edge[i].u>>edge[i].v>>edge[i].w;
        }
        cout<<kruskal()<<endl;
    }
    return 0;
}