POJ 1861 Network (MST kruskal 加权合并 (瓶颈生成树))

来源:互联网 发布:网络写手新手指南 编辑:程序博客网 时间:2024/05/05 23:51
 

最小生成树的一个性质,它的最大边是其他生成树中最小的,但不是充要条件,最小生成树是一棵瓶颈生成树

其他求MST问题:POJ1251 POJ1287

//kruskal 加权合并
#include <cstdio>
#include <algorithm>

using namespace std;

const int maxn=1005;
const int maxm=15005;
struct edge
{
    int u,v,w;
}e[maxm];
int p[maxn],num;
int n,m,ans[maxn],maxw;//树的边数为n-1

inline void init (int x)
{
    p[x]=-1;
}

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

inline int find (int x)
{
    return p[x]<0?x:p[x]=find(p[x]);
}//用这个find函数跑了110ms,下面的79ms , 还是循环快一些

/*int find (int x)
{
    int s;
    for (s=x ; p[s]>=0 ; s=p[s]);
    while (s!=x)
    {
        int tmp=p[x];
        p[x]=s;
        x=tmp;
    }
    return s;
}*/

void Kruskal ()
{
    int i;
    maxw=0;
    for ( i=1 ; i<=n ; ++i) init(i);
    sort (e,e+m,cmp);
    for ( num=0,i=0 ; i<m ; ++i)
    {
        int s=find(e[i].u),t=find(e[i].v);
        //printf("%d,%d",s,t);
        if(s!=t)
        {
            if(maxw<e[i].w)maxw=e[i].w;
            ans[num++]=i;
           
            int tmp=p[s]+p[t];
            p[s]>p[t]?(p[s]=t,p[t]=tmp):(p[t]=s,p[s]=tmp);
            //一开始这里没加括号 WA了一次 ,但是现在也不知道为什么要加
            //if(p[s]>p[t]){p[s]=t;p[t]=tmp;}
            //else {p[t]=s;p[s]=tmp;}
        }
        if(num>=n-1)break;
        //printf(" %d ",e[i].w);
    }
}

int main ()
{
    while (scanf("%d%d",&n,&m)==2)
    {
        int i;
        for ( i=0 ; i<m ; ++i)
        scanf("%d%d%d",&e[i].u,&e[i].v,&e[i].w);
        Kruskal();
        printf("%d\n%d\n",maxw, num);
        for (i=0 ; i<num ; i++)
        printf("%d %d\n",e[ans[i]].u,e[ans[i]].v);
    }
    return 0;
}

原创粉丝点击