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

来源:互联网 发布:h3c端口删除vlan命令 编辑:程序博客网 时间:2024/05/15 16:39

题目貌似出的有点问题,考试的时候理解有点偏差。题干里说的是无向边,然而样例里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
原创粉丝点击