一国之主图

package algorithm;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.Map;
import java.util.Scanner;
import java.util.Set;

/*
现在有一个国家,有n个城市和n-1条边,每条边长为1,这个国家每个城市都可以直接或者间接到底另一个城市,国家的首都为1号,现在
国王决定修一条长度为1的道路,这条道路将连接首都到另一个城市,由于修建道理成本很大,国王联系你,希望找到这边边连接的另一个城市,
使首都到所有城市的最短距离之和最小。

输入:
第一行正整数n
后面n-1行,每行2个数u,v,表示u到v有一条边。数据保证给出的图是一棵树。
输出:
一个整数,为首都到每个城市的总长度之和


输入:
6
1 2
2 3
3 4
3 5
3 6
输出:
8
此时为
d00+d01+d02+d03+d04+d05=0+1+1+2+2+2=8

输入9:
1 2
2 3
3 4
4 5
4 6
5 7
5 8
5 9
输出:15   在城市5和首都修路,距离最小

 
 */


public class KingGraphCaravan {


    private ArrayList vertexList;//存储点的链表
    private static int[][] edges;//邻接矩阵,用来存储边
    private int numOfEdges;//边的数目
    static int maxResult=0;
    
    public KingGraphCaravan(int n) {
        //初始化矩阵,一维数组,和边的数目
        edges=new int[n][n];  //边初始化均为0
        vertexList=new ArrayList(n);  //n个边
        numOfEdges=0;
    }
  //得到结点的个数
    public int getNumOfVertex() {
        return vertexList.size();
    }

    //得到边的数目
    public int getNumOfEdges() {
        return numOfEdges;
    }

    //返回结点i的数据
    public Object getValueByIndex(int i) {
        return vertexList.get(i);
    }
    
    //返回v1,v2的权值
    public int getWeight(int v1,int v2) {
        return edges[v1][v2];
    }

    //插入结点
    public void insertVertex(Object vertex) {
        vertexList.add(vertexList.size(),vertex); //add(index,object) 插入对象
    }

    //插入边
    public void insertEdge(int v1,int v2,int weight) {
        edges[v1][v2]=weight;
        numOfEdges++;
    }
    
    //删除边
    public void deleteEdge(int v1,int v2) {
        edges[v1][v2]=0;
        numOfEdges--;
    }
    
    //得到第一个邻接结点的下标
    public int getFirstNeighbor(int index) {
        for(int j=0;j<vertexList.size();j++) {
            if (edges[index][j]>0) {
                return j;
            }
        }
        return -1;
    }

    //根据前一个邻接结点的下标来取得下一个邻接结点
    public int getNextNeighbor(int v1,int v2) {
        for (int j=v2+1;j<vertexList.size();j++) {
            if (edges[v1][j]>0) {
                return j;
            }
        }
        return -1;
    }

  
    
    //得到第一个邻接结点的下标
    public void getMyFirstNeighbor(int index,boolean[] isVisited ,LinkedList queue
            ,Map<Integer,Integer> mapValue) {
        for(int j=0;j<vertexList.size();j++) {
            
            if (edges[index][j]>0&&isVisited[j]==false) {//未被访问
                
                queue.add(j); //添加
                
                isVisited[j]=true;
                
                mapValue.put(j,mapValue.get(index)+1);
            
               
            }
        }
      
    }


   public void solution(LinkedList queue,boolean[] isVisited,Map<Integer,Integer> mapValue) {
            
      
        if(!queue.isEmpty()){//不为空
            int w=(int) queue.remove();//获取值
            getMyFirstNeighbor(w,isVisited,queue,mapValue);
            solution(queue,isVisited,mapValue);
        }
   
    }
 
  
   public static int distanceSum(Map<Integer,Integer> mapValue){
       int sum=0;
        System.out.println("首都到各城市的距离如下:");
        for(int hh:mapValue.keySet()){
            if(hh!=0){
            int tmp=mapValue.get(hh);
            sum+=tmp;
            }
        }
        return sum;
   }
    
    public static void main(String[] args) {

        
        Scanner sc=new Scanner(System.in);
        String hh=sc.nextLine();
    
        int n=Integer.parseInt(hh); //表示节点
        //String labels[]={"1a","2b","c3","4d","5e"};//结点的标识
        KingGraphCaravan gc=new KingGraphCaravan(n);
        
        for(int i=0;i<n;i++){
              // System.out.print("  "+labels[i]);
               gc.insertVertex(i);
            }
        
        for(int i=0;i<n-1;i++){
            String t=sc.nextLine();
            String[] h1=t.split(" ");
            int v1=Integer.parseInt(h1[0]);
            int v2=Integer.parseInt(h1[1]);
            
            gc.insertEdge(v1-1,v2-1, 1);
            gc.insertEdge(v2-1,v1-1, 1);
        }
        
        
    
    
        
        int minSum=Integer.MAX_VALUE;
        int ii=0;
        boolean flag=true;
        //添加边
        for(int i=1;i<n;i++){
            //if(i!=2)
                //continue;
            flag=true; //默认需要添加
            if(edges[0][i]!=0){ //该边已经存在,无需添加
                flag=false;
            }
            if(flag){
                gc.insertEdge(0,i, 1);
                gc.insertEdge(i,0, 1);
            }
            
        
        
            Map<Integer,Integer> mapValue=new HashMap<Integer,Integer>(); //存储到首都的距离
        
            boolean[] isVisited=new boolean[n]; //默认false
            
            LinkedList queue=new LinkedList(); //队列
            queue.add(0);
            mapValue.put(0,0); //当前节点
            isVisited[0]=true;
            
            gc.solution(queue,isVisited,mapValue);
            
            
            System.out.println("首都到各城市的距离如下:");
            for(int hh1:mapValue.keySet()){
                System.out.println(hh1+"="+mapValue.get(hh1));
            }
            
            for(int k=0;k<n;k++){
                System.out.println();
                for(int k1=0;k1<n;k1++){
                    System.out.print(" "+edges[k][k1]);
                }
                System.out.println();
            }
            
            
            int sum=distanceSum(mapValue);
            
            System.out.println("此时到各城市的距离为:"+sum+"  "+i);
            
            if(minSum>sum){
                minSum=sum;
                ii=i;
            }
            
            //删除其他边
            if(flag){
                gc.deleteEdge(0,i);
                gc.deleteEdge(i,0);
            }
            
            
        }
        
        
        System.out.println("城市为(首都为0,对应输入为0+1=1):添加的公路为从首都0到城市"+ii+",最小距离为:"+minSum);
        System.out.println("名称为首都1到城市"+(ii+1)+" ,修完后最小距离为"+minSum);
        
        
    }

}
 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值