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

今天看到最小生成树的算法
忽然想到 为什么现在的做法都是在 做加法呢?
为什么不尝试一下减法呢?
比如说我们的顶点数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]--;






}





//这里其实应该已经得出最后的最小生成树了 


//由于是刚冒出的想法,可能还有地方存在漏洞,需要验证。