最小生成树的胡思乱想--做减法

来源:互联网 发布:天下足球 知乎 编辑:程序博客网 时间:2024/04/19 11:29

最小生成树的胡思乱想–做减法

今天看到最小生成树的算法
忽然想到 为什么现在的做法都是在 做加法呢?
为什么不尝试一下减法呢?
比如说我们的顶点数n,边数m n和m相差不多
如果我们做加法的话要做 n-1条,假如说n比较大
但是我们如果**做减法,
应该只需要 ( m-(n-1) )条**,
因为前提已经有 (m-n)是一个很小的可以接受的数了,
所以我们可以得出 做减法 需要减去的条数
是会远远小于 做加法 需要加起来的条数的
两者的目的最终都是为了生成最小生成树
就当是我瞎想了,看看能不能证明。

好吧,下面就先记录一下自己不太成熟的算法:

开始需要明确一点,就是最小生成树是针对无向图来说的。

首先,
n为顶点数,m为边数

定义一个G[MAXV][MAXV],将每条边的边权存放进来。
其中,MAXV是最大顶点数。例如:const int MAXV=510;

定义一个int inq[MAXV]={0},标记数组,初始值为0,标记图中的 各个顶点
分别被集合s中si条边包含,则对应的inq[i] = si;

判断是否满足生成树,也就是加入集合s中的边是否将所有的点都包含了进来。

什么时候生成树一定不满足呢?
就是inq数组中1~n 或者是0~n-1编号的n个
顶点有任意一个 inq[i]=0;
这种情况就一定不满足了。

先说一种粗略的,以后再想能不能剪枝。

首先接收外部数据u,v,w。分别是每条边的两个顶点及边权
因为是无向图,而且其实,这个算法考虑了 u->v 了,就
不用重复考虑 v->u 这个地方可以省一点空间和时间

//定义无穷大 const int INF=0x3fffffff;scanf("%d%d",&n,&m);//**此处是以编号0~n-1 为例** //**初始时默认不可达** fill(G[0],G[0]+MAXV*MAXV,INF);for(int i=0;i<m;i++) {    scanf("%d%d%d",&u,&v,&w);    G[u][v]=w;  //如果上面的节省步骤实现,就不用保留其中一个了    inq[u]+=1;      //如果上面的节省步骤实现,这里也会修改     inq[v]+=1;                          //而且要记得是累加!!! }//以上工作全是属于初始化工作//以下是算法阶段

首先我想说一下特殊情况,就是
初始化工作完成之后,inq[]数组中 0~n-1 仍然有 0 值元素
也就是本身提供的图G不足以达到生成最小生成树的条件,此时
也就根本没有必要 去 生成最小生成树,直接退出

//其实我一直在想是不是还有什么更好的容器来替代inq数组//set? map?  priority_queue? queue? stack? vector?bool is_tree=true;for(int i=0;i<n;i++) {    if(inq[i]==0)    {        is_tree=false;        break;    }}if(!is_tree){    printf("无法生成最小生成树!!");    return; }//以上其实还可以加一个判断,以上的处理其实是针对m>n的时候的处理//还可以加下面的判断,有点多此一举,但是下面的判断在某些情况下//省下了遍历的阶段,可以直接退出。 /*     if(m<n-1 )    {        printf("无法生成最小生成树!!");        return;     }*///如果可以生成最小生成树,则继续下面的算法int now_edge=m;     //做减法,要求就是谁大减谁,哪条边大减谁//但是这里也是可以剪枝的,就是如果减去这条边的话,//对应的与其相连的点会出现  inq[u]==0 || inq[v] == 0 的情况,//也就是没剪之前  出现 inq[u]==1 || inq[v] == 1   这样的话//这条边就不可以减 ,继续寻找下一个较大的边。。。直到找到。或者now_edge==n-1时为止//自动排序的话,或许之后可以考虑用到优先队列priority_queue while(now_edge!=n-1){    //以下就是筛选最大元素的过程,或许还能进化     int u=-1,v=-1,MAX=-1;    for(int i=0;i<n;i++)    {        for(int j=i+1;j<n;j++)        {            if( inq[i]>1 && inq[j]>1 && MAX< G[i][j] )            {                u=i;                v=j;                MAX=G[i][j];            }        }    }    G[u][v]=INF;    now_edge--;     inq[u]--;    inq[v]--;}//这里其实应该已经得出最后的最小生成树了 //由于是刚冒出的想法,可能还有地方存在漏洞,需要验证。