关闭

TJU-4117 Happy tree friends(最小生成树)

标签: acmhdojkruskal
240人阅读 评论(0) 收藏 举报
分类:

题目貌似出的有点问题,考试的时候理解有点偏差。题干里说的是无向边,然而样例里Wij != Wji。晕了。以为是最小树形图。

最后和AC同学打听了一下,直接按无向边做就好了,其余的不用管。还有一定要加的那个边的方向不要边。

剩下就是标准的kruskal算法了。先把边按升序排序,再利用并查集向一个集合里加。如果没有冲突(要加的边的两点还没有再一个集合里,那么把这条边的两点相连,权值加入答案)。处理必须要加入的边,先把它的权值加入答案,再把这条边的权值修改为0,排序后,这条边一定会被选中。

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
using namespace std;

const int N=10010;

int n,m,f[N];
struct edge
{
    int x,y;
    int w;
}e[N];

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

int root(int x)
{
    if(f[x]==x) return x;
    f[x]=root(f[x]);
    return f[x];
}

void work()
{
    int i,j,k,t,sum,ans;
    int u,v;

    sum=0;
    m=0;
    memset(e,0,sizeof(e));
    for(i=0;i<=n;i++) f[i]=i;

    for(i=1;i<=n;i++)
        for(j=1;j<=n;j++)
        {
            scanf("%d",&e[m].w);
            e[m].x=i;
            e[m].y=j;
            if(i==j) e[m].w=100000000;
            m++;
        }
    scanf("%d%d",&u,&v);
    sum=e[(u-1)*n+v-1].w;
    e[(u-1)*n+v-1].w=0;
    sort(e,e+m,cmp);
    for(i=0;i<m;i++)
    {
        j=root(e[i].x);
        k=root(e[i].y);
        if(j!=k)
        {
            f[j]=k;
            sum+=e[i].w;
        }
    }

    printf("%d\n",sum);
}

int main()
{
    while(scanf("%d",&n)!=EOF)
        work();
    return 0;
}


0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:25653次
    • 积分:1040
    • 等级:
    • 排名:千里之外
    • 原创:81篇
    • 转载:3篇
    • 译文:0篇
    • 评论:2条
    文章分类
    最新评论