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);
}
}