hdu 1102

最小生成树
一.prime 算法
直接暴力每个点,以每个点为起点找出最优解(距离最短)

#include <bits/stdc++.h>
using namespace std;
typedef __int64 ll;
const int N=107,INF=0x3f3f3f3f;
int cost[N][N],lc[N],vis[N];
int n;
int prime()
{
    for(int i=1; i<=n; i++)
    {
        int mi=INF,pos;
        for(int j=1; j<=n; j++)
            if(!vis[j]&&mi>lc[j])
                mi=lc[j],pos=j;
        vis[pos]=1;//找出花费最少的点后,标记掉避免二次计算
        for(int j=1; j<=n; j++)
            if(!vis[j]&&lc[j]>cost[j][pos])
                lc[j]=cost[j][pos];
    }
    int ans=0;
    for(int i=1; i<=n; i++)
        ans+=lc[i];//答案为每个点的花费总和
    return ans;
}
int main()
{
    int q;
    while(~scanf("%d",&n))
    {
        for(int i=1; i<=n; i++)
            for(int j=1; j<=n; j++)
                scanf("%d",&cost[i][j]);  //i->j的花费
        scanf("%d",&q);
        for(int i=0; i<q; i++)
        {
            int a,b;
            scanf("%d%d",&a,&b);
            cost[a][b]=0;
            cost[b][a]=0;
        }
        memset(lc,INF,sizeof(lc));//每个点的最低花费
        memset(vis,0,sizeof(vis));//是否访问过这个点
        lc[1]=0;//起点花费为0
        printf("%d\n",prime());
    }
}

二 . kruskal
已经连接的点并入一个集合(并查集)

#include <bits/stdc++.h>
using namespace std;
typedef __int64 ll;
const int N=107,INF=0x3f3f3f3f;
int f[N],k;
struct node
{
    int s,d,co;
} po[N*N];
int _find(int x)
{
    if(f[x]!=x) return f[x]=_find(f[x]);
    return f[x];
}
int cmp(node a,node b)
{
    return a.co<b.co;
}
int kruskal()
{
    int ans=0;
    for(int i=0; i<k; i++)
    {
        int fa=_find(po[i].s);
        int fb=_find(po[i].d);
        if(fa!=fb)//不在一个集合内就放入并建边,费用放进ans
        {
            ans+=po[i].co;
            f[fa]=fb;
        }
    }
    return ans;
}
int main()
{
    int n,q;
    while(~scanf("%d",&n))
    {
        k=0;
        for(int i=0; i<=n; i++)
            f[i]=i;
        for(int i=1; i<=n; i++)
            for(int j=1; j<=n; j++)
            {
                scanf("%d",&po[k].co);
                po[k].s=i,po[k].d=j;
                k++;
            }
        int q;
        scanf("%d",&q);
        for(int i=0; i<q; i++)
        {
            int a,b;
            scanf("%d%d",&a,&b);
            int fa=_find(a);
            int fb=_find(b);
            if(fa!=fb) f[fa]=fb;//已经建好的路放进一个集合
        }
        sort(po,po+k,cmp);//按照花费从小到大排序
        printf("%d\n",kruskal());
    }
}

猜你喜欢

转载自blog.csdn.net/oinei/article/details/78657036