//我的天第一次编写竟然这么长,一定有我没找到的方法,啊哈哈哈哈,
/*
北航机试2020/4/13
第二场第二题
*/
#include<stdio.h>
#include<stdlib.h>
#include<vector>
#include<iostream>
using namespace std;
const int INF = 100000000;
int input[100][4];
int n,computerId;
typedef struct node
{
int id;
int type;
int layer;//寻找祖先节点时,保存layer这个属性
node* parent;
node* port1;
node* port2;
node* port3;
node* port4;
}Node,*Tree;
Node* newNode(int id,int type)
{
Node* temp = (Node*)malloc(sizeof(Node));
temp->id = id;
temp->type = type;
temp->layer = 0;
temp->parent = temp->port1 = temp->port2 = temp->port3 = temp->port4 = NULL;
return temp;
}
void createTree(Node* root)//根节点
{
for(int i = 0;i<n;i++)//寻找父节点为root->id的孩子节点
{
if(input[i][2] == root->id)
{
Node* temp = newNode(input[i][0],input[i][1]);
temp->layer = root->layer + 1;
temp->parent = root;
//******节点之间的关系,将刚生成的temp和root关联
if(root->type == 0)//if(temp->type == 0)错误,此外这条语句不写也没关系,下面匹配不到,会default选项
{
switch(input[i][3])
{
case 1:
root->port1 = temp;
break;
case 2:
root->port2 = temp;
break;
case 3:
root->port3 = temp;
break;
case 4:
root->port4 = temp;
break;
default:
break;
}
createTree(temp);//递归建树,使用新生成的子节点建树
}
}
}
return ;
}
/*
按照先序遍历的顺序存储打印机
*/
vector<Node*> printer;
void preOrder(Node* root)
{
if(root)
{
if(root->type == 2) printer.push_back(root);
preOrder(root->port1);
preOrder(root->port2);
preOrder(root->port3);
preOrder(root->port4);
}
}
Node* findChildPosition(Node* root,int id)
{
if(root == NULL) return NULL;
if(root->id == id) return root;
Node *temp1,*temp2,*temp3,*temp4;
temp1 = findChildPosition(root->port1,id);
if(temp1)
return temp1;
temp2 = findChildPosition(root->port2,id);
if(temp2)
return temp2;
temp3 = findChildPosition(root->port3,id);
if(temp3)
return temp3;
temp4 = findChildPosition(root->port4,id);
if(temp4)
return temp4;
return NULL;
}
/*
通过寻找公共祖先节点计算最短距离
按照先序遍历的顺序不断更新printer,最后找到的最短的就是printer编号
*/
//使用层数 + 父指针计算
Node* LeastCommonAncient(Node* root,int id1,int id2)
{
Node* node1 = findChildPosition(root,id1);
Node* node2 = findChildPosition(root,id2);
int layer1 = node1->layer;
int layer2 = node2->layer;
if(layer1<layer2)
{
int c = layer2-layer1;
while(c--)
{
node2 = node2->parent;
}
}
if(layer1> layer2)
{
int d = layer1 - layer2;
while(d--)
{
node1 = node1->parent;
}
}
if(node1 == node2) return node1;
while(node1->parent->id != node2->parent->id)
{
node1 = node1->parent;
node2 = node2->parent;
}
return node1->parent;//return node1;//错误写法
}
int minDistance = INF;
int minDistanceId = 0;//最小的id是从1开始
//通过公共祖先节点,computerId和PrinterId得到最小的距离
int getMinDis(Node* node1,Node* ancient,Node* node2)
{
int sum = 0;
while(node1->parent != ancient)
{
sum++;
node1 = node1->parent;
}
sum++;
while(node2->parent != ancient)
{
sum++;
node2 = node2->parent;
}
sum++;
return sum;
}
//通过全局变量minDistance和minDistanceId
void getMinPrinterId(Node* root)
{
Node *computer = findChildPosition(root,computerId);
for(int i = 0;i<printer.size();i++)
{
Node *node = findChildPosition(root,printer[i]->id);
Node* ancient = LeastCommonAncient(root,computerId,printer[i]->id);
int d = getMinDis(computer,ancient,node);
//cout<<d<<endl;
if(d<minDistance)
{
minDistance = d;
minDistanceId = printer[i]->id;
}
}
}
vector<Node*> path;
void printUpToDown(Node* root,Node* temp)
{
path.push_back(temp);
while(temp->parent != root)
{
path.push_back(temp);
temp = temp->parent;
}
for(int i = path.size()-1;i>=0;i--)
{
if(i == 0)
cout<<path[i]->id<<endl;
else
cout<<path[i]->id<<" ";
}
}
void printDownToUp(Node* root,Node* temp)
{
cout<<temp->id<<" ";
while(temp->parent != root)
{
cout<<temp->id<<" ";
temp = temp->parent;
}
cout<<root->id<<" ";
}
void print(Node* root)
{
Node* node1 = findChildPosition(root,computerId);
Node* node2 = findChildPosition(root,minDistanceId);
Node* ancient = LeastCommonAncient(root,computerId,minDistanceId);
printDownToUp(ancient,node1);
printUpToDown(ancient,node2);
}
int main()
{
/*
输入数据
*/
cin>>n;
for(int i = 0;i<n;i++)
{
cin>>input[i][0]>>input[i][1]>>input[i][2]>>input[i][3];
}
cin>>computerId;
/*
建树
*/
//寻找根节点
int i = 0;
for(i = 0;i<n;i++)
{
if(input[i][2] == 0)
break;
}
//利用根节点建树
Node* root = newNode(input[i][0],input[i][1]);
root->layer = 1;
createTree(root);
preOrder(root);
getMinPrinterId(root);
cout<<minDistanceId<<endl;
print(root);
/*
//TEST
cout<<printer.size()<<endl;
for(int i = 0;i<printer.size();i++)
{
cout<<printer[i]->id<<" ";
}
cout<<endl;
if(findChildPosition(root,9))
cout<<findChildPosition(root,9)->id<<endl;
else
cout<<"Not Find"<<endl;
cout<<LeastCommonAncient(root,6,8)->id<<endl;
*/
return 0;
}
/*
IN:
8
1 0 0 0
2 0 1 1
3 0 1 2
4 0 1 3
5 1 4 3
6 1 3 1
7 2 3 2
8 2 3 3
6
OUT:
7
6 3 7
*/
2019-2-2
猜你喜欢
转载自blog.csdn.net/qq_34686440/article/details/105501497
今日推荐
周排行