17年华为算法大赛源码

之前参加华为软件大赛写的源码,和对题目的理解。

首先是官方给出的题目说明,后面会有我个人的理解。

2017-03-03 原妈 HUAWEI软件精英挑战赛

 

 

比赛问题定义

▌背景

大视频解决方案中,视频业务体验非常关键,视频内容如何有效传送到最终消费者是决定视频体验好坏的核心环节。

 

▌本次赛题基本描述

在给定结构的网络中(如:xx城市的电信网络),为了视频内容快速低成本的传送到每个住户小区,需要在这个给定网络结构中选择一些网络节点附近放置视频内容存储服务器。需要解决的问题是:在满足所有的住户小区视频播放需求的基本前提下,如何选择视频内容存储服务器放置位置,使得成本最小。

 

▌本次赛题通用性描述

网络结构模型:给定一个由若干网络节点(例如路由器、交换机)构成的网络结构无向图,每个节点至少与另外一个节点通过网络链路相连(网络链路特指两个网络节点之间直接相连的网络通路,中间没有其他网络节点,相当于无向图中的一条边),一个节点可以将收到的数据通过网络链路传输给相连的另一个节点,节点本身的转发能力无上限。每条链路的网络总带宽不同(例如某条链路的总带宽为10Gbps)。而每条链路承载的视频传输需要按照占用带宽的多少收取对应网络租用费,每条链路的单位租用费均不同(例如某条链路的租用费为1,000元/Gbps,即1K/Gbps)。某条链路上被占用的带宽总和不得超过该链路的总带宽。

 

消费节点:给定的网络结构中有部分网络节点直接连接到小区住户的网络,每个小区住户网络在这个给定的网络结构图中呈现为一个消费节点,不同消费节点的视频带宽消耗需求不同。

 

视频内容服务器:视频内容服务器存放视频内容(如:电影影片、电视剧等),视频内容服务器的视频数据流可以经由网络节点与链路构成的网络路径流向消费节点,视频内容服务器的输出能力没有上限,可以服务多个消费节点,一个消费节点也可以同时从多台视频内容服务器获取视频流。部署一台视频内容服务器需要费用成本(例如300,000元/台,即300K/台),所有服务器的成本均相同。

 

比赛程序内容:请你设计一个程序寻找最优的视频内容服务器部署方案:从网络结构模型中选择一部分网络节点,在其上/附近一对一的部署视频内容服务器,视频内容服务器与对应的这个节点直连,与对应的这个网络节点之间的通信没有带宽限制,也没有通信成本。提供的部署方案需要使得视频流从视频内容服务器经过一些网络节点和链路到达消费节点,满足所有消费节点的视频带宽消耗需求,并使得耗费的总成本(视频内容服务器部署成本+带宽租用成本)最低。部署方案不仅需要包括部署视频内容服务器的节点位置,而且还要包括每个消费节点与所有视频内容服务器之间的网络路径以及路径上占用的带宽。

 

▌比赛胜负规则

若给定的网络拓扑模型不存在满足条件的方案,则输出无解,程序运行时间越短者胜出。若存在满足条件的方案,则成本越低者胜出。若两个方案的成本相同,则程序运行时间越短者胜出。

 

▌补充说明

1. 两个网络节点之间最多仅存在一条链路,链路上下行方向的网络总带宽相互独立,并且上下行方向的总带宽与网络租用费相同。例如对于网络节点A与B之间的链路,该条链路上的总带宽为10Gbps,单位租用费为1K/Gbps,则表示A->B、B->A两个方向上的网络总带宽分别为10Gbps,并且租用费均为1K/Gbps。如果某条数据流在该链路A->B方向的占用带宽为3Gbps,那么该数据流在该链路的租用费为3K,并且该链路A->B方向的剩余可用带宽为7Gbps。而B->A方向的剩余可用带宽不受该数据流的影响,仍为10Gbps。

2. 每个网络节点最多仅能连接一个消费节点,每个消费节点仅能连接一个网络节点。消费节点与连接的网络节点之间的链路总带宽无限大,并且网络租用费为零。

3. 网络节点数量不超过1000个,每个节点的链路数量不超过20条,消费节点的数量不超过500个。

4. 链路总带宽与单位网络租用费为[0, 100]的整数,视频内容服务器部署成本与消费节点的视频带宽消耗需求为[0,5000]的整数。

5. 部署方案中,网络路径上的占用带宽必须为大于等于0的整数。

6. “满足消费节点的带宽消耗需求”是指输出给消费节点的带宽总和不得小于该消费节点的视频带宽消耗需求。

7. 每个网络节点上最多仅可部署一台视频内容服务器

 

▌比赛用例示例

 

上图为A市网络拓扑图,黑色圆圈为网络节点,红色圆圈为消费节点,圆圈内的数字为节点编号。节点之间的连线为网络链路。链路上的标记(x, y)中,x表示链路总带宽(单位为Gbps),y表示每Gbps的网络租用费。消费节点相连链路上的数字为消费节点的带宽消耗需求(单位为Gbps)。

 

现在假设需要在该网络上部署视频内容服务器,满足所有消费节点的需求(注意:对于任意用例至少存在一个可行解,即在每个消费节点直接相连的网络节点上部署一台服务器)。那么一个成本较低的方案可以如下图所示,其中绿色圆圈表示已部署的视频内容服务器,通往不同消费节点的网络路径用不同颜色标识,并附带了占用带宽的大小:

 

但该方案的成本不一定是最低的。因此现在需要参赛者提供的程序能够针对不同的比赛用例,给出成本最低的部署方案。

 

程序输入与输出

 

▌输入文件格式

程序输入为一个以空格分隔的文本文件,文件每行以换行符(ASCII’\n’即0x0a)为结尾。

 

文件格式为:

网络节点数量网络链路数量消费节点数量

(空行)

视频内容服务器部署成本

(空行)

链路起始节点ID 链路终止节点ID 总带宽大小 单位网络租用费

…………….(如上链路信息若干行)

(空行)

消费节点ID相连网络节点ID 视频带宽消耗需求

…………….(如上终端用户信息若干行)

(文件结束)

 

说明:

1. 网络节点ID与消费节点ID均为以0为起始的整数。

2. 文本中出现的所有数值均为大于等于0的整数,数值上限为100000。

 

▌输入文件示例(参照第一节中的用例)

28 45 12 // 注:28个网络节点,45条链路,12个消费节点

 

100  // 注:服务器部署成本为100

 

0 16 8 2 // 注:链路起始节点为0,链路终止节点为16,总带宽为8,单位网络租用费为2

0 26 13 2

0 9 14 2

0 8 36 2

(以下省略若干行网络节点信息)

 

0 8 40 // 注:消费节点为0,相连网络节点ID为8,视频带宽消耗需求为40

1 11 13

2 22 28

3 3 45

4 17 11

5 19 26

6 16 15

7 13 13

8 5 18

9 25 15

10 7 10

11 24 23

 

▌输出文件格式

程序输出为一个以空格分隔的文本文件,文件每行以换行符(ASCII’\n’即0x0a)为结尾。

 

程序结果按如下格式输出:

网络路径数量

(空行)

网络节点ID-01网络节点ID-02 …… 网络节点ID-n 消费节点ID 占用带宽大小

…………….(如上网络路径信息若干行,每条网络路径由若干网络节点构成,路径的起始节点ID-01表示该节点部署了视频内容服务器,终止节点为某个消费节点)

(文件结束)

 

说明:

1. 网络路径数量不得超过50000条。

2. 单条路径的节点数量不得超过1000个。

3. 不同网络路径可按任意先后顺序输出。

4. 网络节点ID与消费节点ID的数值必须与输入文件相符合,如果ID数值不存在于输入文件中,则将被视为无效结果。

5. 文本文件中出现的所有数值必须为大于等于0的整数,数值大小不得超过100000。

 

▌输出文件示例(参照第一节中的用例部署方案)

19 // 注:共输出19条网络路径

 

0 9 11 1 13 // 注:起始网络节点ID为0,经由ID为9、11等网络节点到达消费节点为1,占用带宽为13

0 7 10 10

0 8 0 36

0 6 5 8 13

(以下省略网络路径若干行)

 

单个用例的评分机制

 

▌用例的排名机制

按下面流程对参赛者结果进行排名:

Step1: 对于提交的结果,进行合法性检验(详见题目描述);

Step2: 单个用例的程序运行时间不得超过90s;

若不满足上述的结果则本用例得分为0;

Step3: 计算部署方案的成本,成本越小,排名越优;

Step4: 在成本相同的结果里,用程序运行时间进行排名,时间越短,排名越优。

 

▌单个用例的评分标准如下

根据上面排名流程得到的排名,使用标准分计分(排名第一的提交者为100分)。

若所有人均未得到正确结果,则所有人均得分为0。

 

最终得分机制

 

比赛平台会使用N个测试用例判题,该N个测试用例分为初级、中级、高级三个等级,参赛者对于每个测试用例都会得到一个百分制分数,使用加权平均分(初级权重为0.2,中级权重为0.3,高级权重为0.5)作为该参赛者的最终得分。

 

▌特别说明:

1. 前期系统会提供练习用例用于判题与排名,4月1日开始提供正式比赛用例。截止初赛结束前,系统将在比赛用例上自动运行选手最后一次提交的代码并进行评分,所得分数为初赛最终成绩。

2. 在比赛初期,比赛平台只提供初级、中级的练习用例,故此时满分为50分,在比赛后期,才会提供高级练习用例(具体时间会在网站公告通知),此时满分才为100。



--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

从工程的角度讲这是一个设施选址的问题,从算法的角度讲可以归纳为一个图论的问题。

那么关键就来了,首先要找出和一般图论问题的区别。

一.首先是主要问题

1.节点分为两种类型,有链路节点和消费节点。

2.由节点链接的边上不是单纯的距离,而是双向带宽和单位带宽租用费用。

二.然后是解决方案

1.两种节点我选择了新建两种链表作为数据模型保存节点,存储消费节点的链表中每个消费节点保存相连的链路节点id,为每个链路节点新建一个链表,其中保存有这个节点所有相连的链路节点

2.在单向有向边中保存保存剩余属性和单位租用费用

--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

//消费节点,定义为一个链表的头
public class consumptionNode {
	private int consumptionNodeId;//消费节点id,用于确定哪一个消费节点
	private LinkNode nextLinkNodeId;//链路节点id,用于确定哪一个链路节点
	private int bandwidthRequirement;//定义一个参数保存贷款需求
	public consumptionNode(int consumptionNodeId,LinkNode nextLinkNodeId,int bandwidthRequirement){
		this.consumptionNodeId=consumptionNodeId;
		this.nextLinkNodeId=nextLinkNodeId;
		this.bandwidthRequirement=bandwidthRequirement;
	}
	
	
	
	
	
	
	
	public int getConsumptionNodeId() {
		return consumptionNodeId;
	}
	public void setConsumptionNodeId(int consumptionNodeId) {
		this.consumptionNodeId = consumptionNodeId;
	}
	public LinkNode getNextLinkNodeId() {
		return nextLinkNodeId;
	}
	public void setNextLinkNodeId(LinkNode nextLinkNodeId) {
		this.nextLinkNodeId = nextLinkNodeId;
	}
	public int getBandwidthRequirement() {
		return bandwidthRequirement;
	}
	public void setBandwidthRequirement(int bandwidthRequirement) {
		this.bandwidthRequirement = bandwidthRequirement;
	}
	

}

public class EmptyQueueException extends Exception {

	public EmptyQueueException(String string) {
		// TODO Auto-generated constructor stub
	}

}

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.Closeable;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.LinkedList;
import java.util.List;

public final class FileUtil//util利用
{
    /** 
     * read file and output
     * @param filePath
     * @param spec//spec规格 
     * @return
     * @author
     * @since 2016-3-1
     */
    public static String[] read(final String filePath, final Integer spec)
    {
        File file = new File(filePath);//获取文件eg. File file = new File("D:/hust/file.txt");
        // file check
        if ((!isFileExists(file)) || 
        		(!file.canRead()))
        {
            System.out.println("file [" + filePath + "] is not exist or cannot read!!!");
            return null;
        }
        
        List<String> lines = new LinkedList<String>();
        BufferedReader br = null;
        FileReader fb = null;
        try
        {
            fb = new FileReader(file);//使用带有指定文件的String参数的构造方法。创建该输入流对象。并关联源文件。
            br = new BufferedReader(fb);

            String str = null;
            int index = 0;
            while (((spec ==  null) || index++ < spec) && (str = br.readLine()) != null)
//readline表示该方法读取一行文本,当遇到换行符"\n",回车符"\r"或者回车符后面紧跟着换行符时,该行结束并返回。
//没有数据时,将会一直处于等待状态。(这里的一行不是物理的一行,而是以分隔号界定的一行)
            {
                lines.add(str);
            }
        }
        catch (IOException e)
        {
            e.printStackTrace();
        }
        finally
        {
            closeQuietly(br);
            closeQuietly(fb);
        }

        return lines.toArray(new String[lines.size()]);
    }
    /** 
     * write file
     * @param filePath 
     * @param content 
     * @param append true or false
     * @return
     * @author s00274007
     * @since 2016-3-1
     */                     
    public static int write (final String filePath, final String[] contents, final boolean append)
    {
        File file = new File(filePath);
        if (contents == null)
        {
            System.out.println("file [" + filePath + "] invalid!!!");//invalid无效
            return 0;
        }

        if (isFileExists(file) && (!file.canRead()))
        {
            return 0;
        }

        FileWriter fw = null;
        BufferedWriter bw = null;
        try
        {
            if (!isFileExists(file))
            {
                file.createNewFile();
            }

            fw = new FileWriter(file, append);
            bw = new BufferedWriter(fw);
            for (String content : contents)//遍历contents
            {
                if (content == null)
                {
                    continue;
                }
                bw.write(content);
                bw.newLine();
            }
        }
        catch (IOException e)
        {
            e.printStackTrace();
            return 0;
        }
        finally
        {
            closeQuietly(bw);
            closeQuietly(fw);
        }

        return 1;
    }

    private static void closeQuietly(Closeable closeable)
    {
        try
        {
            if (closeable != null)
            {
                closeable.close();
            }
        }
        catch (IOException e)
        {
        }
    }

    private static boolean isFileExists(final File file)
    {
        if (file.exists() && file.isFile())
        {
            return true;
        }

        return false;
    }

}

import java.util.LinkedList;
import java.util.List;

public class Graphs {
	
	List<consumptionNode> root=new LinkedList<>();
	List<rootLinkNode> LinkRoot=new LinkedList<>();
	private int consumptionNodeId;//消费节点id,用于确定哪一个消费节点
	private LinkNode nextLinkNodeId;//链路节点id,用于确定哪一个链路节点
	private int bandwidthRequirement;//定义一个参数保存贷款需求

	
	
	//text测试用例
	//public void getinfo(){
	//	int num=5;
	//	for(int i=0;i<num;i++){
	//		consumptionNodeId=i;
	//		nextLinkNodeId=null;
	//		bandwidthRequirement=i;
	//		addNode( consumptionNodeId, nextLinkNodeId, bandwidthRequirement);
	//	}
	//	for(int i=0;i<num;i++){
	//		int m=root.get(i).getConsumptionNodeId();
	//		System.out.println();
	//		
	//	}
	//	
	//}
	
	
	
	
	//text2
	public void getInfo2(){
		int size=5;
		buildLinkRootList(size);
		for(int i=0;i<size;i++){
			int preNodeId=i;
					setNextLinkNodeId(null);
					int localNodeId=i;
					int totalBandwidth=i;
					addLinkNode( i, i+1,i,i,i);
		}
		
		for(int i=0;i<size;i++){
			System.out.println(LinkRoot.get(i).getLocalNodeId()+"其临接链表是"+LinkRoot.get(i).getNextLinkNode().getLocalNodeId());
		}
	}
	
	
	
	
	
	
	//这个方法是添加根节点的方法
	public void addNode(int total,int consumptionNodeId,LinkNode nextLinkNodeId,int bandwidthRequirement){
		int totalConsumptionNode = 0;
		
		for(int i=0;i<totalConsumptionNode;i++){
			consumptionNode e=new consumptionNode(consumptionNodeId, nextLinkNodeId, bandwidthRequirement);
			root.add(e);
		}
			
	}
	public void addNode(int consumptionNodeId,LinkNode nextLinkNodeId,int bandwidthRequirement){
			consumptionNode e=new consumptionNode(consumptionNodeId, nextLinkNodeId, bandwidthRequirement);
			root.add(e);
				
	}
	//返回root的制定元素
	public consumptionNode returnNode(int i){ 
		return this.root.get(i);
		
	}
	
	
	
	//添加网络节点根节点的方法
	public void addRootLinkNode(int i){
		rootLinkNode e=new rootLinkNode(i,null);
		LinkRoot.add(e);
	}
	

	
	
	
	
	//这个方法用于创建临接表表头节点
	public void buildLinkRootList(int size){
		for(int i=0;i<size;i++){
			rootLinkNode rln=new rootLinkNode(i,null);
			LinkRoot.add(rln);
			
		}
		
	}
	
	
	
	
	
	
	
	//这个方法是添加临接点的方法
	public void addLinkNode(int preNodeId,int localNodeId,int totalBandwidth,int nextNodeId,int unitRentalCost){
		int addPreId=localNodeId;
		LinkNode nextLinkNode=new LinkNode(addPreId,nextNodeId,1000,null,1);//
		LinkNode LN=new LinkNode( preNodeId,localNodeId,totalBandwidth,nextLinkNode,unitRentalCost);
		LinkRoot.get(preNodeId).setNextLinkNodeForRoot(LN);
		
	}






	public int getConsumptionNodeId() {
		return consumptionNodeId;
	}






	public void setConsumptionNodeId(int consumptionNodeId) {
		this.consumptionNodeId = consumptionNodeId;
	}






	public LinkNode getNextLinkNodeId() {
		return nextLinkNodeId;
	}






	public void setNextLinkNodeId(LinkNode nextLinkNodeId) {
		this.nextLinkNodeId = nextLinkNodeId;
	}






	public int getBandwidthRequirement() {
		return bandwidthRequirement;
	}






	public void setBandwidthRequirement(int bandwidthRequirement) {
		this.bandwidthRequirement = bandwidthRequirement;
	}
	
	
	
	
	
	public List<consumptionNode> getroot() {
		return this.root;
	}






	


}

public class LinkNode {
	private int localNodeId;
	private int totalBandwidth;
	private int upBandwidth;
	private int downBandwidth;
	private LinkNode nextLinkNode;
	private int preNodeId;
	private int unitRentalCost;
	//所有链路节点的preNodeId保存为链路根节点
	public LinkNode(int preNodeId,int localNodeId,int totalBandwidth,LinkNode nextLinkNode,int unitRentalCost){
		this.localNodeId=localNodeId;
		this.preNodeId=preNodeId;
		this.totalBandwidth=totalBandwidth;
		this.upBandwidth=totalBandwidth;
		this.downBandwidth=totalBandwidth;
		this.setNextLinkNode(nextLinkNode);
		this.unitRentalCost=unitRentalCost;
		
	}
	
	
	
	
	
	
	public int getLocalNodeId() {
		return localNodeId;
	}
	public void setLocalNodeId(int localNodeId) {
		this.localNodeId = localNodeId;
	}
	public int getTotalBandwidth() {
		return totalBandwidth;
	}
	public void setTotalBandwidth(int totalBandwidth) {
		this.totalBandwidth = totalBandwidth;
	}
	public int getUpBandwidth() {
		return upBandwidth;
	}
	public void setUpBandwidth(int upBandwidth) {
		this.upBandwidth = upBandwidth;
	}
	public int getDownBandwidth() {
		return downBandwidth;
	}
	public void setDownBandwidth(int downBandwidth) {
		this.downBandwidth = downBandwidth;
	}
	public LinkNode getNextLinkNode() {
		return nextLinkNode;
	}
	public void setNextLinkNode(LinkNode nextLinkNode) {
		this.nextLinkNode = nextLinkNode;
	}






	public int getPreNodeId() {
		return preNodeId;
	}






	public void setPreNodeId(int preNodeId) {
		this.preNodeId = preNodeId;
	}

}

public class LLNode {
	private int data;
	private LLNode nextNode;
	public LLNode(int data,LLNode nextNode){
		this.setDataForLLNode(data);
		this.setNextNodeForLLNode(nextNode);		
	}
	public LLNode(int data){
		this.data=data;
		this.nextNode=null;
		
	}
	public int getDataForLLNode() {
		return data;
	}
	public void setDataForLLNode(int data) {
		this.data = data;
	}
	public LLNode getNextNodeForLLNode() {
		return nextNode;
	}
	public void setNextNodeForLLNode(LLNode nextNode) {
		this.nextNode = nextNode;
	}
}

public class LLQueue {
	private LLNode frontNode;
	private LLNode rearNode;
	public LLQueue(){
		this.setFrontNode(null);
		this.setRearNode(null);
	}
	private LLQueue(LLNode frontNode,LLNode rearNode){
		this.setFrontNode(frontNode);
		this.setRearNode(rearNode);
		
	}
	public LLNode getFrontNode() {
		return frontNode;
	}
	public void setFrontNode(LLNode frontNode) {
		this.frontNode = frontNode;
	}
	public LLNode getRearNode() {
		return rearNode;
	}
	public void setRearNode(LLNode rearNode) {
		this.rearNode = rearNode;
	}
	public static LLQueue createQueue(){
		return new LLQueue();
	}
	public boolean isEmpty(){
		return (frontNode==null);
		//为空则返回1,不为空返回0
	}
	public void enQueue(int data){
		LLNode newNode=new LLNode(data);
		if(rearNode!=null){
			rearNode.setNextNodeForLLNode(newNode);
		}
		rearNode=newNode;
		if(frontNode==null){
			frontNode=newNode;
		}
	}
	public int deQueue(){
		int data;//int 类型不能赋值为null
		if(isEmpty()){
			System.out.println("这个队列是空的");	
			return -1;
		}else{
			data=frontNode.getDataForLLNode();
			frontNode=frontNode.getNextNodeForLLNode();
		}
		return data;
	}
}
//public class Miracle2 {

//}
import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Queue;

 /*
  * 求解无向图的单源最短路径
  */
 public class Miracle2 {
	 
	 
	
	 
	 
	
     public class Vertex{//这个方法定义顶点的基本属性
    	 
    	 
    	 
    	 
    	 
    	 
         private String vertexLabel;//顶点标识
         private List<Edge> adjEdges;//与该顶点邻接的边(点),每一个Vertex里都有一个链表存储其边
         private int dist;//顶点距离(该顶点到起始顶点的距离)
         private Vertex preNode;//顶点的前顶点
         //构造一个实例
         public Vertex(String vertexLabel) {
             this.vertexLabel = vertexLabel;
             adjEdges = new LinkedList<>();
            dist = Integer.MAX_VALUE;//为距离设置为最大值
             preNode = null;
         }
     }
     private class Edge{//边由顶点决定
         private Vertex endVertex;
         //构造实例
         public Edge(Vertex endVertex) {
             this.endVertex = endVertex;
         }
     }
     
     private Map<String, Vertex> nonDirectedGraph;//保存了图中所有的顶点,边的关系以List形式保存在Vertex类中,通
    // 过键值对保存未处理顶点
     private Vertex startVertex;//图的起始顶点
     
     public Miracle2(String graphContent) {//定义一个构造方法
         nonDirectedGraph = new LinkedHashMap<>();
         buildGraph(graphContent);
     }
     
     private  void buildGraph(String graphContent){//通过传进来的内容构造图
         String[] lines = graphContent.split("\n");
         
         String startNodeLabel, endNodeLabel;
         Vertex startNode, endNode;
         

        		 
         //以上是变量的定义
         for(int i = 0; i < lines.length; i++){
             String[] nodesInfo = lines[i].split(",");
             startNodeLabel = nodesInfo[1];
             endNodeLabel = nodesInfo[2];
             
             endNode = nonDirectedGraph.get(endNodeLabel);
             if(endNode == null){
                 endNode = new Vertex(endNodeLabel);
                 nonDirectedGraph.put(endNodeLabel, endNode);
             }
             
             startNode = nonDirectedGraph.get(startNodeLabel);//从键值对获得标签
             if(startNode == null){
                 startNode = new Vertex(startNodeLabel);
                 nonDirectedGraph.put(startNodeLabel, startNode);
             }
             Edge e = new Edge(endNode);
             //对于无向图而言,起点和终点都要添加边
             endNode.adjEdges.add(e);
             startNode.adjEdges.add(e);
         }
         startVertex = nonDirectedGraph.get(lines[0].split(",")[1]);//总是以文件中第一行第二列的那个标识顶点作为源点
     }
     
     public void unweightedShortestPath(){
         unweightedShortestPath(startVertex);
     }
    
     
     /*
      * 
      * 需要一个队列来保存图中的顶点,初始时,源点入队列,然后以广度的形式向外扩散求解其他顶点的最短路径
      */
     private void unweightedShortestPath(Vertex s){//该方法计算原点s到无向图各个顶点的最短路径
         //初始化
         Queue<Vertex> queue = new LinkedList<>();//用队列存储各个点
         s.dist = 0;
         queue.offer(s);//将源点dist设置为0并入队列,offer用于添加元素入数列
         
         while(!queue.isEmpty()){
             Vertex v = queue.poll();//检索并删除队列的头
             for (Edge e : v.adjEdges) {//扫描v的邻接边(点)
                 if(e.endVertex.dist == Integer.MAX_VALUE){//如果这个顶点(e.endVertex)未被访问(每个顶点只会入队列一次)
                     e.endVertex.dist = v.dist + 1;//更新该顶点到源点的距离
                     queue.offer(e.endVertex);//将顶点放入队列,准备进行下一次换原电遍历
                     e.endVertex.preNode = v;//设置该顶点的前驱顶点
                 }//end if
             }//end for         
             }//end while
     }
     
     //打印图中所有顶点到源点的距离及路径
     public  void showDistance(){
         Collection<Vertex> vertexs = nonDirectedGraph.values();//collection是创建一个存储元素的容器
         for (Vertex vertex : vertexs) {
             System.out.print(vertex.vertexLabel + "<--");
             Vertex tmpPreNode = vertex.preNode;
             while(tmpPreNode != null){
                System.out.print(tmpPreNode.vertexLabel + "<--");
                 tmpPreNode = tmpPreNode.preNode;
             }
             System.out.println("distance=" + vertex.dist);
         }
     }
}
public class rootLinkNode {
	private int localNodeId;
	private LinkNode nextLinkNode;
	public rootLinkNode(int localNodeId,LinkNode nextLinkNode){
		this.setLocalNodeId(localNodeId);
		this.setNextLinkNodeForRoot(nextLinkNode);
		
	}
//public addRootLinkNode(i){
//		}
	public LinkNode getNextLinkNode() {
		return nextLinkNode;
	}
	public void setNextLinkNodeForRoot(LinkNode nextLinkNode4) {
		//this.nextLinkNode = nextLinkNode;
		if(this.nextLinkNode==null){
			this.nextLinkNode = nextLinkNode4;
		}else{
		LinkNode temp=this.nextLinkNode;
		while(temp.getNextLinkNode()!=null){
			temp=temp.getNextLinkNode();
			
		}
		temp.setNextLinkNode(nextLinkNode4);}
	}
	public int getLocalNodeId() {
		return localNodeId;
	}
	public void setLocalNodeId(int localNodeId) {
		this.localNodeId = localNodeId;
	}
}
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

public class run {
	public static void main(String[] args){
		FileUtil fu=new FileUtil();
		//String filePath="D:\\info.txt";
	//	final int spec=4;
		
		//String[] infos=fu.read(filePath, spec);
		
		//int size=infos.length;
		//String info = null;
		//String infoOut=null;
		//for(int i=0;i<size;i++){
		//	 info=infos[i];
		//	System.out.println(info);
		//    infoOut=infoOut+info+"\r";
		//	
	//	}
		
		//Miracle2 mi =new Miracle2(infoOut);
		//mi.showDistance();
		
		
		//String info3="789\n123";
		//System.out.println(info3);
		
		
		
		
		int serverDeploymentCost;//服务器部署成本
		int numOfConsumptionNode;//消费节点数量
		int numOfNetworkLink;//网络链路数量
		int numOfLinkNode;//链路节点数量
		
		Graphs g=new Graphs();
		//g.getInfo2();
		String filePath2="D:\\case0.txt";
		int spec =3;
		String[] infos=fu.read(filePath2, spec);
//		for(int i=0;i<spec;i++){
//			System.out.println(infos[i]);
//		}
		String temp=infos[0];
		System.out.println(temp);
		
		
		
		
		//text3测试按空格分开是否有误
		String[] splitTemp=temp.split("\\s");
//		for(int i=0;i<3;i++){//当i=3时是0,1,2行被选中
//			System.out.println(splitTemp[i]);
//		}
		numOfConsumptionNode=Integer.parseInt(splitTemp[2]);
		numOfNetworkLink=Integer.parseInt(splitTemp[1]);
		numOfLinkNode=Integer.parseInt(splitTemp[0]);
		serverDeploymentCost=Integer.parseInt(infos[2]);
		//28个网络节点,45条链路,12个消费节点
		
		
		
		
		//System.out.println(numOfConsumptionNode);
		//System.out.println(numOfNetworkLink);
		//System.out.println(numOfLinkNode);
		
		//计算需要的总共需要的spec
		spec=5+numOfNetworkLink+numOfConsumptionNode;
		String[] finalinfos=fu.read(filePath2, spec);
		//计算读取链路数需要的开始和结束行
		//第几行-1就是所需行号
		int startNumOfLink=4;
		int endNumOfLink=4+numOfNetworkLink-1;
		//计算读取消费节点数需要的开始和结束行
		int startNumOfConsumptionNode=endNumOfLink+2;
		int endNumOfConsumptionNode=startNumOfConsumptionNode+numOfConsumptionNode-1;
		
		
		System.out.println(endNumOfConsumptionNode);
		
		//先存储消费节点,下面是为消费节点赋值并创建的代码
		
		for(int i=startNumOfConsumptionNode;i<endNumOfConsumptionNode+1;i++){
			String temp2=finalinfos[i];
		String[]	consumptiontemp=temp2.split("\\s");
		//int i=startNumOfConsumptionNode;	
		//consumptiontemp=finalinfos[i].split("\\s");
			
			
			
			int consumptionNodeId=Integer.parseInt(consumptiontemp[0]);//消费节点id,用于确定哪一个消费节点
		    LinkNode nextLinkNodeId=new LinkNode(i, Integer.parseInt(consumptiontemp[1]), 1000, null,0);//链路节点id,用于确定哪一个链路节点
		    //Integer.parseInt(consumptiontemp[1])
		    int bandwidthRequirement=Integer.parseInt(consumptiontemp[2]);//定义一个参数保存贷款需求
		    
		    
		    
		    //消费节点0,相连网络节点ID为8,视频带宽消耗需求为40 
		    
		    
		    
		    
		    //原打算在这里新建添加消费节点的方法,但是该方
		    //法应存在与图中,应直接从图调用
		    //List<consumptionNode> runroot=g.getroot();
			//consumptionNode e=new consumptionNode(consumptionNodeId,nextLinkNodeId,bandwidthRequirement);
			//runroot.add<>;
		    
		    
		    
		    //从上图获得的参数构建消费节点链表
		    g.addNode(consumptionNodeId, nextLinkNodeId, bandwidthRequirement);
		}
		
		//test
//		for(int i=0;i<numOfConsumptionNode;i++){
//			
//			System.out.println(g.returnNode(i).getConsumptionNodeId());
//			System.out.println(g.returnNode(i).getNextLinkNodeId().getLocalNodeId());
//			System.out.println(g.returnNode(i).getBandwidthRequirement());
//			
//		}
		
		
		
		
		
		
		//添加链路头结点的方法
		//numOfLinkNode网络链路节点数量
		int localNodeId;
		LinkNode nextLinkNode;
		for(int i=0;i<numOfLinkNode;i++){
			//rootLinkNode(i,null);
			g.addRootLinkNode(i);
		}
		 //System.out.println("下面是测试链路头结点程序");
		//System.out.println(numOfLinkNode);
		//for(int i=0;i<50;i++){
		//	System.out.println(g.LinkRoot.get(i).getLocalNodeId());
		//}
		
		
		
		//添加链路节点的方法
		
		 //for(int i=startNumOfLink;i<endNumOfConsumptionNode+1;i++){
		for(int i=startNumOfLink;i<endNumOfLink;i++){
			//定义链路节点基本元素
			int lnlocalNodeId;
		    int lntotalBandwidth;
			LinkNode lnnextLinkNode;
			int lnpreNodeId;
			int lnunitRentalCost;
			String temp3=finalinfos[i];
		    String[] consumptiontemp=temp3.split("\\s");
		    lnpreNodeId=Integer.parseInt(consumptiontemp[0]);
		    lnlocalNodeId=Integer.parseInt(consumptiontemp[1]);
		    lntotalBandwidth=Integer.parseInt(consumptiontemp[2]);
		    lnunitRentalCost=Integer.parseInt(consumptiontemp[3]);
		    //新建节点之后加进去
		    lnnextLinkNode=new LinkNode(lnpreNodeId, lnlocalNodeId, lntotalBandwidth, null, lnunitRentalCost);
		    LinkNode reverseLnnextLinkNode;
		    reverseLnnextLinkNode=new LinkNode(lnlocalNodeId, lnpreNodeId, lntotalBandwidth, null, lnunitRentalCost);
		    if(g.LinkRoot.get(lnpreNodeId).getNextLinkNode()==null){
		    	g.LinkRoot.get(lnpreNodeId).setNextLinkNodeForRoot(lnnextLinkNode);
		    }else{
		    	 LinkNode temp4=g.LinkRoot.get(lnpreNodeId).getNextLinkNode();
		    	 LinkNode temp5=g.LinkRoot.get(lnpreNodeId).getNextLinkNode();
				    while(temp4!=null&&temp4.getLocalNodeId()!=lnlocalNodeId){
				    	temp5=temp4;
				    	temp4=temp4.getNextLinkNode();
				    
				    }
				    //if(temp4==null){if(temp4.getLocalNodeId()!=lnlocalNodeId)
				    if(temp4==null){
				    	temp5.setNextLinkNode(lnnextLinkNode);
				    	//g.LinkRoot.get(lnpreNodeId).setNextLinkNodeForRoot(lnnextLinkNode);
				    }
				    
		    }
		    
		    
		    //反向代码
		    if(g.LinkRoot.get(lnlocalNodeId).getNextLinkNode()==null){
		    	g.LinkRoot.get(lnlocalNodeId).setNextLinkNodeForRoot(reverseLnnextLinkNode);
		    }else{
		    	 LinkNode temp4=g.LinkRoot.get(lnlocalNodeId).getNextLinkNode();
		    	 LinkNode temp5=g.LinkRoot.get(lnlocalNodeId).getNextLinkNode();
				    while(temp4!=null&&temp4.getLocalNodeId()!=lnpreNodeId){
				    	temp5=temp4;
				    	temp4=temp4.getNextLinkNode();
				    
				    }
				    if(temp4==null){
				    	g.LinkRoot.get(lnlocalNodeId).setNextLinkNodeForRoot(reverseLnnextLinkNode);
				    }
				    
		    }
		   
		    //g.LinkRoot.get(lnpreNodeId).setNextLinkNodeForRoot(lnnextLinkNode);
		    //LinkNode temp4=g.LinkRoot.get(lnpreNodeId).getNextLinkNode();
		   // while(){
		    	
		  //  }
		
		}
		
		//这里起始节点命名为preNodeId
		//链路起始节点为0,链路终止节点为16 ,总带宽为8,单位网络租用费为2
		
//		System.out.println("下面是测试数据");
//		for(int i =0;i<numOfLinkNode;i++){
//			LinkNode temp6=g.LinkRoot.get(i).getNextLinkNode();
//			System.out.println(temp6.getLocalNodeId());
//		}
//		System.out.println(g.LinkRoot.get(1).getNextLinkNode().getLocalNodeId());
		
		
		//总测试用例
		//我们已经得到
		//28个网络节点,45条链路,12个消费节点
		//服务器部署成本为100
		//链路节点信息
		//链路起始节点为0,链路终止节点为16 ,总带宽为8,单位网络租用费为2
		//消费节点信息
		//消费节点0,相连网络节点ID为8,视频带宽消耗需求为40 
		System.out.printf("有%d个网络节点,%d个链路,%d个消费节点", numOfLinkNode,numOfNetworkLink,numOfConsumptionNode);
		
	
		
		//从消费结点开始遍历,存储在队列中
		//任取一消费节点,检查其是否满足链路带宽等于其需求,满足则开始配对
	int rootSize=g.root.size();
	//System.out.println(rootSize);
	//定义一个集合保存满足单路的结点
	//list<int> singleWayconsumption=new LinkList<>;
	
	int destination;
	int countOfSingleWayConsumption=0;
	int[] nextNodeForConsumptionNode=new int[rootSize];
	for(int i=0;i<rootSize;i++){
		//第一个消费节点的第一个链路节点提供的带宽
		int idFornextNodeofConsumptionNode=g.root.get(i).getNextLinkNodeId().getLocalNodeId();
		//System.out.println(idFornextNodeofConsumptionNode);
		nextNodeForConsumptionNode[i]=idFornextNodeofConsumptionNode;
		int firstConsumptionLinkNodeBandWith=g.LinkRoot.get(idFornextNodeofConsumptionNode).getNextLinkNode().getTotalBandwidth();
		//System.out.println(idFornextNodeofConsumptionNode);
	//	int firstConsumptionLinkNodeBandWith=g.root.get(i).getNextLinkNodeId().getNextLinkNode().getTotalBandwidth();
		
		if(g.root.get(i).getBandwidthRequirement()<=firstConsumptionLinkNodeBandWith){
			//singleWayConsumption[countOfSingleWayConsumption]=g.root.get(i).getConsumptionNodeId();
			
			countOfSingleWayConsumption++;
		}
		
		
//		//text
//		for(int d=0;d<countOfSingleWayConsumption;d++){
//			System.out.println(singleWayConsumption[d]);
//			}
		}
	int[] singleWayConsumption=new int[countOfSingleWayConsumption] ;
	int countFor2=0;
//	System.out.println(countOfSingleWayConsumption);
	
	for(int i=0;i<rootSize;i++){
		//第一个消费节点的第一个链路节点提供的带宽
		//int firstConsumptionLinkNodeBandWith2=g.root.get(c).getNextLinkNodeId().getNextLinkNode().getTotalBandwidth();
		int idFornextNodeofConsumptionNode2=g.root.get(i).getNextLinkNodeId().getLocalNodeId();
		int firstConsumptionLinkNodeBandWith2=g.LinkRoot .get(idFornextNodeofConsumptionNode2).getNextLinkNode().getTotalBandwidth();
		
		
		if(g.root.get(i).getBandwidthRequirement()<=firstConsumptionLinkNodeBandWith2){
			singleWayConsumption[countFor2]=g.root.get(i).getConsumptionNodeId();
			countFor2++;
			//countOfSingleWayConsumption++;
		}
	
}
	
	//map.put(1, 5);
	//System.out.println(map.get(1));
	System.out.println("检验这个数是多少");
	System.out.println(countOfSingleWayConsumption);	
	searchMatrix matrixForRun=new searchMatrix();
	int[][] a=matrixForRun.createMatrix(numOfLinkNode,numOfLinkNode);
	matrixForRun.assignment(a, numOfLinkNode, numOfLinkNode);
	//定义一个数组记录链路可使用的最大带宽	//开始遍历并保存路径
	//获得所有消费节点的临界点,保存在数组中,进行比较	//int[][] route=null;
	//int[][] route=new int[1000][10];
	//当一个索引=-1时,表示该行遍历结束	//nextNodeForConsumptionNode
	for(int i=0;i<numOfLinkNode;i++){
		a[i][i]=1;
	}
	LLQueue llqueue=new LLQueue();
	//建立一个hashmap存储邻接点为键值,消费节点为value
			Map map=new HashMap<>();
			for(int i=0;i<rootSize;i++){
				map.put(g.root.get(i).getNextLinkNodeId().getLocalNodeId(), g.root.get(i).getConsumptionNodeId());		
			}
		
	for(int i=0;i<countOfSingleWayConsumption;i++){
		int thisConsumptionNode=singleWayConsumption[i];
		System.out.println("这是一次遍历");
		
		//route[i][0]=thisConsumptionNode;
		llqueue.enQueue(thisConsumptionNode);
		//route[i][0]=1;		//route[i][1]=nextNodeForConsumptionNode[thisConsumptionNode];
		//llqueue.enQueue(nextNodeForConsumptionNode[thisConsumptionNode]);
		llqueue.enQueue(g.root.get(thisConsumptionNode).getNextLinkNodeId().getLocalNodeId());
		//int temp11=nextNodeForConsumptionNode[thisConsumptionNode];
		int temp11=g.root.get(thisConsumptionNode).getNextLinkNodeId().getLocalNodeId();
		System.out.println(thisConsumptionNode);
		System.out.println(temp11);
		//while(g.LinkRoot.get(temp11).getNextLinkNode().getLocalNodeId()!=null){
		levelSearch(temp11,g,nextNodeForConsumptionNode,llqueue,i,a,map);	
		//}		//g.LinkRoot.get(temp11).getNextLinkNode()!=null//判断一个节点下一个指向点不为空的语句		
//g.LinkRoot.get(temp11).getNextLinkNode().getLocalNodeId()
		//获得下一个节点的id		//compare(g. inkRoot.get(temp11).getNextLinkNode().getLocalNodeId(),nextNodeForConsumptionNode);	
	//比较其临界点是否有链路直连的临接点的方法
	}
	//int[] route = null;//route[0]=0;//route[1]=1;//route[2]=2;//	System.out.println("测试链表是否为空");
//	rootLinkNode temp13=g.LinkRoot.get(1);
//	LinkNode temp14=temp13.getNextLinkNode();//	while(temp14!=null){//		System.out.println(temp14.getLocalNodeId());
//		temp14=temp14.getNextLinkNode();
//	}//	System.out.println("测试结束");	
	}

	public static void levelSearch(int numOfNode,Graphs g,int[] aggregate,LLQueue llqueue,int i,int[][]iswalk,Map map){
		//每个链路节点的第一个节点是rootlinknode属性
		rootLinkNode temp=g.LinkRoot.get(numOfNode);
		LinkNode temp1=null;
		int maxBandWidth=10000;
//		while(temp.getNextLinkNode()!=null&&compare(temp.getLocalNodeId(),aggregate)){//			temp1=temp.getNextLinkNode();
//			j++;//			route[i][j]=temp1.getLocalNodeId();
//			if(maxBandWidth>=temp1.getUpBandwidth()){//				maxBandWidth=temp1.getUpBandwidth();//			}
//			//		}
		levelSearchForNode(numOfNode,g,aggregate,llqueue,i,temp,temp1,maxBandWidth,iswalk,map);
	}
	//这个方法遍历子节点
	public static void levelSearchForNode(int numOfNode,Graphs g,int[] aggregate,LLQueue llqueue,int i,rootLinkNode temp
,LinkNode temp1,int maxBandWidth,int[][]iswalk,Map map){
		//findNewRootNode(temp112,temp111,aggregate,iswalk,llqueue,numOfNode,g,map);
		//尝试引入临接矩阵,标签已索引过的边
		//LinkNode temp=g.LinkRoo
			temp=g.LinkRoot.get(numOfNode);
//			System.out.println(numOfNode);t.get(numOfNode);
		 //levelSearchForNode(numOfNode,g,aggregate,route,i,j,temp,temp1,maxBandWidth);
 		while(temp.getNextLinkNode()!=null&&compare(temp.getNextLinkNode().getLocalNodeId(),aggregate)
&&conversionBoolean(iswalk[temp.getLocalNodeId()][temp.getNextLinkNode().getLocalNodeId()])){
			iswalk[temp.getLocalNodeId()][temp.getNextLinkNode().getLocalNodeId()]=1;
			iswalk[temp.getNextLinkNode().getLocalNodeId()][temp.getLocalNodeId()]=1;
			temp1=temp.getNextLinkNode();
			//j++;
			//route[i][j]=temp1.getLocalNodeId();
			llqueue.enQueue(temp1.getLocalNodeId());
			//			System.out.println("下面是135135");
//6			System.out.println(temp.getNextLinkNode().getLocalNodeId());//			System.out.println("下面是j");
//			System.out.println(j);
			if(maxBandWidth>=temp1.getUpBandwidth()){
				maxBandWidth=temp1.getUpBandwidth();
			}
			numOfNode=temp1.getLocalNodeId();
//			System.out.println(iswalk[temp.getLocalNodeId()][temp.getNextLinkNode().getLocalNodeId()]);
//			System.out.println(conversionBoolean(iswalk[temp.getLocalNodeId()][temp.getNextLinkNode().getLocalNodeId()]));
			levelSearchForNode(numOfNode,g,aggregate,llqueue,i,temp,temp1,maxBandWidth,iswalk,map);
		}
    	if(temp.getNextLinkNode()==null){
		
		
		LLNode tempForIf=null;
		tempForIf=llqueue.getFrontNode();
		while(tempForIf.getNextNodeForLLNode()!=llqueue.getRearNode()){
			tempForIf=tempForIf.getNextNodeForLLNode();
		} 
		llqueue.setRearNode(tempForIf);
		
		numOfNode=tempForIf.getNextNodeForLLNode().getDataForLLNode();
		rootLinkNode temp111=g.LinkRoot.get(numOfNode);
		LinkNode temp112=null;
		//由根节点转为一般节点
		if(temp111.getNextLinkNode()!=null){
			temp112=temp111.getNextLinkNode();
		}
    	
 		findNewRootNode(temp112,temp111,aggregate,iswalk,llqueue,numOfNode,g,map);}
    	else{
    		rootLinkNode temp111=null;
    		LinkNode temp112=temp.getNextLinkNode();
    		System.out.println( temp112.getLocalNodeId());
    		System.out.println( temp112.getNextLinkNode().getLocalNodeId());
        findNewRootNode(temp112,temp111,aggregate,iswalk,llqueue,numOfNode,g,map);
    	}
//		if(temp.getNextLinkNode()==null){
			
			
//			LLNode tempForIf=null;
//			tempForIf=llqueue.getFrontNode();
//			while(tempForIf.getNextNodeForLLNode()!=llqueue.getRearNode()){
//				tempForIf=tempForIf.getNextNodeForLLNode();
//			} 
//			llqueue.setRearNode(tempForIf);
			
//			numOfNode=tempForIf.getNextNodeForLLNode().getDataForLLNode();
//			rootLinkNode temp111=g.LinkRoot.get(numOfNode);
//			LinkNode temp112=null;
			//由根节点转为一般节点
//			if(temp111.getNextLinkNode()!=null){
//				temp112=temp111.getNextLinkNode();
//			}
			//if(temp112.getNextLinkNode()!=null&&compare(temp112.getNextLinkNode().getLocalNodeId(),aggregate)
&&conversionBoolean(iswalk[temp111.getLocalNodeId()][temp112.getNextLinkNode().getLocalNodeId()])){
				
			//}
			//获得未访问的节点	
			//如果下一个节点又为空了,只能递归调用此函数
 //           while(temp112.getNextLinkNode()!=null&&compare(temp112.getNextLinkNode().getLocalNodeId(),aggregate)
&&conversionBooleanReverse(iswalk[temp111.getLocalNodeId()][temp112.getNextLinkNode().getLocalNodeId()])){
//				if(temp112.getNextLinkNode()==null){
					
//				}
 //           	temp112=temp112.getNextLinkNode();
//			}
			//while(temp111.getNextLinkNode()!=null&&compare(temp.getLocalNodeId(),aggregate)
&&conversionBoolean(iswalk[temp.getLocalNodeId()][temp.getNextLinkNode().getLocalNodeId()])){			
			//}
//            iswalk[temp111.getLocalNodeId()][temp112.getNextLinkNode().getLocalNodeId()]=1;
//			iswalk[temp112.getNextLinkNode().getLocalNodeId()][temp111.getLocalNodeId()]=1;
//			numOfNode=temp112.getLocalNodeId();
//		    temp=g.LinkRoot.get(numOfNode);
//			llqueue.enQueue(numOfNode);
//			temp1=null;
//			levelSearchForNode(numOfNode,g,aggregate,llqueue,i,temp,temp1,maxBandWidth,iswalk,map);
//		}
		//if(compareReverse(temp.getNextLinkNode().getLocalNodeId(),aggregate)){
		//获取未访问的下个节点恰好为消费节点邻接点的点,输入消费节点
//			if(temp.getNextLinkNode()!=null&&compareReverse(temp.getNextLinkNode().getLocalNodeId(),aggregate)
&&conversionBoolean(iswalk[temp.getLocalNodeId()][temp.getNextLinkNode().getLocalNodeId()])){	
			//打印路径
//			route[i][j]=-1;
//			llqueue.enQueue(temp.getNextLinkNode().getLocalNodeId());
//			iswalk[temp.getLocalNodeId()][temp.getNextLinkNode().getLocalNodeId()]=1;
//			iswalk[temp.getNextLinkNode().getLocalNodeId()][temp.getLocalNodeId()]=1;
//			llqueue.enQueue(Integer.parseInt(String.valueOf(map.get(temp.getNextLinkNode().getLocalNodeId()))));
//			
//			System.out.println("下面是打印数据");
//			for(int d=0;d<route[i].length;d++){
//				System.out.println(route[i][d]);
//			}
//			LLNode tempforQueue=llqueue.getFrontNode();
//			while(tempforQueue.getNextNodeForLLNode()!=llqueue.getRearNode()){
//				int data=tempforQueue.getDataForLLNode();
//				System.out.println(data);
//				tempforQueue=tempforQueue.getNextNodeForLLNode();
//			}
//			System.out.println(llqueue.getRearNode().getDataForLLNode());
//			llqueue.setRearNode(tempforQueue);
//			while(llqueue.getFrontNode()!=llqueue.getRearNode()){
//				int data=llqueue.deQueue();
//				System.out.println(data);
//			}
//			System.out.println(llqueue.getFrontNode().getDataForLLNode());
//			llqueue.setFrontNode(null);
//			llqueue.setRearNode(null);
//			System.out.println("结束了");	
//			numOfNode=tempforQueue.getDataForLLNode();
//			temp1=g.LinkRoot.get(numOfNode).getNextLinkNode();
//			 while(temp1.getNextLinkNode()!=null&&conversionBoolean(iswalk[numOfNode][temp1.getLocalNodeId()])){
//				 temp1=temp1.getNextLinkNode();
//			 }
//			 if(conversionBooleanReverse(iswalk[numOfNode][temp1.getLocalNodeId()])){
//				 numOfNode=temp1.getLocalNodeId();
//				 temp=g.LinkRoot.get(numOfNode);
///					temp1=null;
//			 }else{
//				 LLNode tempForElse=llqueue.getFrontNode();
//				while(tempForElse.getNextNodeForLLNode()!=llqueue.getRearNode()){
//					tempForElse=tempForElse.getNextNodeForLLNode();
//				}
//				llqueue.setRearNode(tempForElse);
//				numOfNode=tempForElse.getDataForLLNode();
//				temp=g.LinkRoot.get(numOfNode);
//			 }
			
//			levelSearchForNode(numOfNode,g,aggregate,llqueue,i,temp,temp1,maxBandWidth,iswalk,map);
//		}
	}
	
	//最后返回正确,说明该节点成立
	private static boolean compare(int element,int[] aggregate) {
		// TODO Auto-generated method stub
		int a=aggregate.length;
		//int a=8;		//for(int i=0;i<a;i++){					//}
		int c=0;
		//while(element!=aggregate[c]&&c<a){
			while(c<a&&element!=aggregate[c]){	
			c++;
		}
		if(c==a){
			return true;
		}else{
			return false;
		}
	}
	//没访问过返回1,正向转化值输入-1返回true
	public static boolean conversionBoolean(int a){
		if(a==-1){
			return true;
		}else{
			return false;
		}
	}
	//反向的转化值,未访问由TRUE转为false,输入1返回true
	public static boolean conversionBooleanReverse(int a){
		if(a==-1){
			return false;
		}else{
			return true;
		}
	}
	//aggregate集合//输入待比较的元素和比较元素的集合//比较没有返回1,比较有返回0    
	
		//定义反向的比较有返回true,没有返回false
	private static boolean compareReverse(int element,int[] aggregate) {
		// TODO Auto-generated method stub
		int a=aggregate.length;
		//int a=8;		//for(int i=0;i<a;i++){					//}
		int c=0;
		//while(element!=aggregate[c]&&c<a){
			while(c<a&&element!=aggregate[c]){	
			c++;
		}
		if(c==a){
			return false;
		}else{
			return true;
		}
	}
	public void replaceRootNode(int numOfNode,Graphs g,LinkNode temp1,rootLinkNode temp,int[][] iswalk,LLNode rearNode){
		temp1=g.LinkRoot.get(numOfNode).getNextLinkNode();
		 while(temp1.getNextLinkNode()!=null&&conversionBoolean(iswalk[numOfNode][temp1.getLocalNodeId()])){
			 temp1=temp1.getNextLinkNode();
		 }
		 if(conversionBoolean(iswalk[numOfNode][temp1.getLocalNodeId()])){
			 numOfNode=temp1.getLocalNodeId();
			 temp=g.LinkRoot.get(numOfNode);
				temp1=null;
		 }else{
			 if(rearNode.getDataForLLNode()!=g.LinkRoot.get(numOfNode).getLocalNodeId()){				 
			 }
		 }
		
	}
	public static void findNewRootNode(LinkNode temp112,rootLinkNode temp111,int[] aggregate
,int[][] iswalk,LLQueue llqueue,int numOfNode,Graphs g,Map map){
		  while(temp112.getNextLinkNode()!=null&&compare(temp112.getNextLinkNode().getLocalNodeId(),
aggregate)&&conversionBooleanReverse(iswalk[temp111.getLocalNodeId()][temp112.getNextLinkNode().getLocalNodeId()])){
//				if(temp112.getNextLinkNode()==null){					
//				}
          	temp112=temp112.getNextLinkNode();
			}
		  if(temp112.getNextLinkNode()==null){
				LLNode tempForIf=null;
				tempForIf=llqueue.getFrontNode();
				while(tempForIf.getNextNodeForLLNode()!=llqueue.getRearNode()){
					tempForIf=tempForIf.getNextNodeForLLNode();
				} 
				llqueue.setRearNode(tempForIf);
				
				numOfNode=tempForIf.getNextNodeForLLNode().getDataForLLNode();
				 temp111=g.LinkRoot.get(numOfNode);
				 temp112=null;
				//由根节点转为一般节点
				if(temp111.getNextLinkNode()!=null){
					temp112=temp111.getNextLinkNode();
					findNewRootNode(temp112,temp111,aggregate,iswalk,llqueue,numOfNode,g,map);
				}
			  
		  }
		  else{
			  if(temp112.getNextLinkNode()!=null&&conversionBooleanReverse(iswalk[temp111.getLocalNodeId()]
[temp112.getNextLinkNode().getLocalNodeId()])){
				  temp112=temp112.getNextLinkNode();
				  findNewRootNode(temp112,temp111,aggregate,iswalk,llqueue,numOfNode,g,map);
			  }else{
				  if(temp112.getNextLinkNode()!=null&&compare(temp112.getNextLinkNode().getLocalNodeId(),aggregate)
&&conversionBoolean(iswalk[temp111.getLocalNodeId()][temp112.getNextLinkNode().getLocalNodeId()])){
					  llqueue.enQueue(temp112.getNextLinkNode().getLocalNodeId());
						iswalk[temp112.getLocalNodeId()][temp112.getNextLinkNode().getLocalNodeId()]=1;
						iswalk[temp112.getNextLinkNode().getLocalNodeId()][temp112.getLocalNodeId()]=1;
						llqueue.enQueue(Integer.parseInt(String.valueOf(map.get(temp112.getNextLinkNode().getLocalNodeId()))));
						
						System.out.println("下面是打印数据");
//						for(int d=0;d<route[i].length;d++){
//							System.out.println(route[i][d]);
//						}
						LLNode tempforQueue=llqueue.getFrontNode();
						while(tempforQueue.getNextNodeForLLNode()!=llqueue.getRearNode()){
							int data=tempforQueue.getDataForLLNode();
							System.out.println(data);
							tempforQueue=tempforQueue.getNextNodeForLLNode();
						}
						System.out.println(llqueue.getRearNode().getDataForLLNode()); 
						llqueue.setRearNode(tempforQueue);
						temp112=temp112.getNextLinkNode();
						  findNewRootNode(temp112,temp111,aggregate,iswalk,llqueue,numOfNode,g,map);
				  }else{if(compare(temp112.getNextLinkNode().getLocalNodeId(),aggregate)
&&conversionBooleanReverse(iswalk[temp111.getLocalNodeId()][temp112.getNextLinkNode().getLocalNodeId()])){
					  temp112=temp112.getNextLinkNode();
					  findNewRootNode(temp112,temp111,aggregate,iswalk,llqueue,numOfNode,g,map);
				  }}
			  }
		  }
		
	}
	//从消费结点开始遍历,存储在队列中	//任取一消费节点,检查其是否满足链路带宽等于其需求,满足则开始配对
	//private static void shorestPath() {	// TODO Auto-generated method stub	//	g	//}
	//思路	//建立一个临接矩阵表示边是否访问过	//要利用主代码新建的变量,就要在方法中输入变量	//依次输入要使用的变量
	//g.LinkRoot.get(temp11).getNextLinkNode()!=null	//判断一个节点下一个指向点不为空的语句	
//g.LinkRoot.get(temp11).getNextLinkNode().getLocalNodeId()	//获得下一个节点的id
//compare(g. inkRoot.get(temp11).getNextLinkNode().getLocalNodeId(),nextNodeForConsumptionNode);	//比较其临界点是否有链路直连的临接点的方法	
//这个方法只遍历头结点
	//parameter要开始遍历的链路头结点,已建立缓存的图,保存消费点临结点的集合,保存路径的数组,第几个消费节点的下标
	
public class searchMatrix {
	private int[][] matrix;

	public int[][] createMatrix(int x,int y) {
		matrix=new int[x][y];
		return matrix;
	}
	public void assignment(int[][] matrix,int x,int y){
		//分配
		for(int i=0;i<x;i++){
			for(int j=0;j<y;j++){
				matrix[i][j]=-1;
			}
		}
	}
	//当值为-1时表示未访问,为1表示访问过
	public void setMatrix(int[][] matrix) {
		this.matrix = matrix;
	}
	public int getValue(int x,int y){
		return matrix[x][y];
	}
	public void setValue(int x,int y,int value){
		matrix[x][y]=value;
	}
	public int[][] getMatrix() {
		return matrix;
	}
}





评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值