有向图最小生成树

int pre[maxn];//最短弧前驱
int vis[maxn];//点标记
int used[maxn];//查环过程的标记
double Map[maxn][maxn];//存图关系
int n,m,u,v,len;

double zhuliu(int root)
{
    double sum=0;
    int i,j,k;
    memset(vis,0,sizeof vis);
    while(1){
        for(i=1;i<=n;i++){  //1、求最短弧集合pre
            if(vis[i]||i==root) continue;
            pre[i]=i;
            for(int j=1;j<=n;j++)   //找i点的最短前驱弧
                if(!vis[j]&&Map[j][i]<Map[pre[i]][i])
                    pre[i]=j;
            if(pre[i]==i) return -1;    //弱图不连通
        }
        for(i=1;i<=n;i++){  //2、查环
            if(vis[i]||i==root) continue;
            memset(used,0,sizeof used);
            used[root]=1;
            k=i;
            while(!used[k]){
                used[k]=1;
                k=pre[k];
            }
            if(k!=root) break;//存在环
        }
        if(i>n){     //不存在环了
            for(j=1;j<=n;j++)
                if(j!=root&&!vis[j])
                    sum+=Map[pre[j]][j];
            return sum;
        }
        i=k;  //3、下面将这个环缩到i点;
        do{   //4、先累加环记录下环权值
            sum+=Map[pre[k]][k];
            k=pre[k];
        }while(k!=i);
        do{//5、修改环上点的前驱边,为准备环收缩
            for(j=1;j<=n;j++)
                if(!vis[j]&&Map[j][k]<INF&&j!=pre[k])
                    Map[j][k]-=Map[pre[k]][k];
            k=pre[k];
        }while(k!=i);
        for(j=1;j<=n;j++){       //6、环收缩到i点
            if(j==i||vis[j])continue;
            for(k=pre[i];k!=i;k=pre[k]){        //k点的对外距离给i点
                if(Map[i][j]>Map[k][j])Map[i][j]=Map[k][j];
                if(Map[j][i]>Map[j][k])Map[j][i]=Map[j][k];
            }
        }
        for(k=pre[i];k!=i;k=pre[k])vis[k]=1;//7、将环上除i外全标记
    }
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值