支撑树的插点问题

问题描述




支撑树的插点数目问题






支撑树插点数目问题算法描述:




注意:这里的输入还应加上d和B

算法的java实现:


package sy2;

import sy1.*;

public class TheInsertNodeOfSpanningTree {
	public final static int Inf=Integer.MAX_VALUE;//表示整型无穷大,用来标识两个顶点是否有边相连
	public int[][] M;//有向图邻接矩阵
	public Vnode[] V;//有向图的顶点集
	public Vnode X[];//反圈中的顶点集
	public Arc F[];//反圈中的边集合
	public int ArcNum;
	public int num=0;//反圈中的边数
	public int InsertTree[][];
	public Vnode Insert[];
	public TheInsertNodeOfSpanningTree(int M[][],Vnode V[],int ArcNum) {
		// TODO Auto-generated constructor stub
		this.M=M;
		this.V=V;
		this.ArcNum=ArcNum;
		X=new Vnode[V.length];
		X[0]=new Vnode(V[0].getV(),V[0].getVw());
		V[0].setFlag(true);
		for(int i=1;i<X.length;i++){
			X[i]=new Vnode("",i);
		}
		F=new Arc[ArcNum];
		for(int i=0;i<ArcNum;i++){
			F[i]=new Arc(null,null,Inf);
		}
	}
	public boolean TheMinimalSpanningTree(){
		boolean flag1=true;
		boolean flag=false;//用来判断反圈中的顶点集是否等于图的顶点集
		int min=Inf;//用来求取最小权值弧长
		int index1=0;//用来表示权值最小的非反圈对应点的位置
		int index2=0;//用来表示权值最小的反圈对应点的位置
		while(flag==false){//表示反圈中的顶点集不等于图的顶点集
			min=Inf;
			for(int i=0;i<X.length;i++){
				if(!X[i].getV().equals("")){
					for(int j=0;j<V.length;j++){
						if(V[j].isFlag()==false && M[X[i].getVw()][V[j].getVw()]!=Inf){
							if(M[X[i].getVw()][V[j].getVw()]<min){
								min=M[X[i].getVw()][V[j].getVw()];//寻找权值最小的边
								index1=j;
								index2=i;
								//System.out.println(index2+" "+index1);
							}// if
						}// if
					}// for
				}// if
			}// for
			if(index1!=-1){//表示反圈不为空
				X[index1]=new Vnode(V[index1].getV(),index1);//将该点加入反圈的点集合
				V[index1].setFlag(true);
				F[num]= new Arc(X[index2],V[index1],M[index2][index1]);//将该边加入反圈集合
				num++;
			}
			else{//表示若反圈为空
				if(num==V.length-1){
					flag=true;
				}else{
					//System.out.println("此图不连通,不存在最小支撑树!");
					for(int i=0;i<ArcNum;i++){
						F[i]=new Arc(null,null,Inf);
					}
					for(int i=1;i<X.length;i++){
						X[i]=new Vnode("",i);
					}
					flag1=false;
					break;
				}
			}
			index1=-1;
			index2=-1;
		}//while
		return flag1;
	}
	public boolean InsertTree(int B,int d){
		boolean flag=true;//判断能否找到支撑树的插点树
		int sum=0;
		int Num=0;//表示总的加点数
		if(!TheMinimalSpanningTree()){
			flag=false;//表示不存在最小支撑树
		}
		int InsertNum[]=new int[num];//记录支撑树每条边上的插点数
		for(int i=0;i<num;i++){
			if(F[i].getWeight()!=Inf){
				sum=sum+F[i].getWeight();
			}
		}
		if(sum>B){
			flag=false;//表示不存在最小支撑树
		}
		else{
			//System.out.println(num);
			for(int i=0;i<num;i++){
				double t;
				if(F[i].getWeight()!=Inf){
					t=(double)F[i].getWeight()/d;
					if(t==(int)t){
						InsertNum[i]=(int)t-1;
					}else{
						InsertNum[i]=(int)t;
					}//else
				}//if
				Num=Num+InsertNum[i];
			}//for
			System.out.println("总插点树:"+Num);
			InsertTree=new int[V.length+Num][V.length+Num];
			Insert=new Vnode[V.length+Num];
			for(int i=0;i<V.length+Num;i++){
				for(int j=0;j<V.length+Num;j++){
					if(i<V.length && j<V.length){
						InsertTree[i][j]=M[i][j];
					}
					else{
						InsertTree[i][j]=Inf;
					}
				}
				if(i<V.length){
					Insert[i]=V[i];
				}else{
					Insert[i]=new Vnode("",i);
				}
			}
			int index=V.length;
			String s;
			for(int i=0;i<num;i++){
				if(InsertNum[i]!=0){//表示对应这条边插点
					InsertTree[F[i].getFirstNode().getVw()][F[i].getLastNode().getVw()]=Inf;
					InsertTree[F[i].getLastNode().getVw()][F[i].getFirstNode().getVw()]=Inf;
					InsertTree[F[i].getFirstNode().getVw()][index]=d;
					InsertTree[index][F[i].getFirstNode().getVw()]=d;
					s="v"+Integer.toString(index+1);
					Insert[index]=new Vnode(s,index);
					for(int j=0;j<InsertNum[i]-1;j++){
						InsertTree[index][index+1]=InsertTree[index+1][index];
						index++;
						s="v"+Integer.toString(index+1);
						Insert[index]=new Vnode(s,index);
					}
					InsertTree[index][F[i].getLastNode().getVw()]=InsertTree[F[i].getLastNode().getVw()][index]=F[i].getWeight()-InsertNum[i]*d;
				}//if
			}//for
		}//if
		return flag;
	}
	public static void main(String args[]) throws Exception{
		MyGraph G=new MyGraph();
		G.createGraph();
		System.out.println("请输出所构建图的邻接矩阵:");
		for(int i=-1;i<G.getVexNum();i++){
			if(i<0){
				System.out.print("          ");
				for(int j=0;j<G.getVexNum();j++){
					System.out.print(G.getVex(j)+"         ");
				}
				System.out.println();
			}else{
				for(int j=-1;j<G.getVexNum();j++){
					if(j<0){
						System.out.print(G.getVex(i)+"         ");
					}
					else{
                         if(G.arcs[i][j]==Inf){
                        	 System.out.print("INF"+"         ");
						}
                         else{
                        	 System.out.print(G.arcs[i][j]+"         ");	
                         }					
					}//else
				}// if
				System.out.println();
			}// for
		}//else
		TheInsertNodeOfSpanningTree Insert=new TheInsertNodeOfSpanningTree(G.arcs,G.V,G.getArcNum());
		if(!Insert.InsertTree(10, 1)){
			System.out.println("不存在最小支撑树!");
		}
		else{
			System.out.println("最小支撑树是:");
			for(int i=0;i<Insert.num;i++){
				if(Insert.F[i].getWeight()!=Inf){
					System.out.println(Insert.F[i].getFirstNode().getV()+"------"+Insert.F[i].getLastNode().getV()+":weight="+Insert.F[i].getWeight());
				}
			}
			System.out.println("其加细树是:");
			for(int i=-1;i<Insert.InsertTree.length;i++){
				if(i<0){
					System.out.print("            ");
					for(int j=0;j<Insert.InsertTree.length;j++){
						System.out.print(Insert.Insert[j].getV()+"        ");
					}
					System.out.println();
				}else{
					for(int j=-1;j<Insert.InsertTree.length;j++){
						if(j<0){
							System.out.print(Insert.Insert[i].getV()+"         ");
						}
						else{
	                         if(Insert.InsertTree[i][j]==Inf){
	                        	 System.out.print("INF"+"       ");
							}
	                         else{
	                        	 System.out.print(Insert.InsertTree[i][j]+"         ");	
	                         }					
						}//else
					}// if
					System.out.println();
				}// else
			}//for
		}//else
	}
}


程序分析:

本程序共包含1个class,3个method:
class:TheInsertNodeOfSpanningTree
method:
public boolean TheMinimalSpanningTree(): 利用反圈法求最小支撑树
public boolean InsertTree(int B,int d): 对相应的支撑树进行插点
main: 程序的主方法,调用上面的两个方法,找到对应图的最小支撑树,进行插点,并输出插点后的加细树

本实验总的来说难点在构造支撑树的加细树,下面我用一点例子来描述我的构造过程:




从上面的描述就可以找到构造邻接矩阵的规律,具体体现为如下的代码:


for(int i=0;i<num;i++){
				if(InsertNum[i]!=0){//表示对应这条边插点
					InsertTree[F[i].getFirstNode().getVw()][F[i].getLastNode().getVw()]=Inf;			InsertTree[F[i].getLastNode().getVw()][F[i].getFirstNode().getVw()]=Inf;
					InsertTree[F[i].getFirstNode().getVw()][index]=d;
					InsertTree[index][F[i].getFirstNode().getVw()]=d;
					s="v"+Integer.toString(index+1);
					Insert[index]=new Vnode(s,index);
					for(int j=0;j<InsertNum[i]-1;j++){
						InsertTree[index][index+1]=InsertTree[index+1][index];
						index++;
						s="v"+Integer.toString(index+1);
						Insert[index]=new Vnode(s,index);
					}
	InsertTree[index][F[i].getLastNode().getVw()]=F[i].getWeight()-InsertNum[i]*d;
InsertTree[F[i].getLastNode().getVw()][index]=F[i].getWeight()-InsertNum[i]*d;
				}//if
			}//for


实例演示:

对下面给出的两个图进行插点:



对于第一幅图:




对于第二幅图:



这里的第二幅图是不连通的,因此不存在其最小支撑树,插点也就没有意义了


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值