Harry Potter’s Exam (an application of Dijkstra algorithm)

In Professor McGonagall's class of Transfiguration, Harry Potter is learning how

to transform one object into another by some spells. He has learnt that, to turn a cat
into a mouse one can say docamo! To reverse the effect, simply say decamo!
Formally speaking, the transfiguration spell to transform between object A and object
B is said to be S if there are two spells, doS and deS, to turn A into B and vice versa,
respectively.
In some cases, short-cut spells are defined to make transfiguration easier. For
example, suppose that the spell to transform a cat to a mouse is docamo, and that to
transform a mouse into a fatmouse is dofamo, then to turn a cat into a fatmouse one
may say docamodofamo! Or if a shot-cut spell is defined to be cafam, one may get
the same effect by saying docafam!
Time is passing by quickly and the Final Exam is coming. By the end of the
transfiguration exam, students will be requested to show Professor McGonagall
several objects transformed from the initial objects they bring to the classroom.
Each of them is allowed to bring 1 object only.
Now Harry is coming to you for help: he needs a program to select the object he
must take to the exam, so that the maximum length of any spell he has to say will be
minimized. For example, if cat, mouse, and fatmouse are the only three objects
involved in the exam, then mouse is the one that Harry should take, since it will take a
6-letter spell to turn a mouse into either a cat or a fatmouse. Cat is not a good choice
since it will take at least a 7-letter spell to turn it into a fatmouse. And for the same
reason Harry must not take a fatmouse.
Input Specification:
Your program must read test cases from the standard input.
Input consists of several test cases. For each test case, the first line contains
two positive integers N (≤100) and M, which are the total number of objects involved
in the exam and the number of spells to be tested, respectively. For the sake of
simplicity, the objects are numbered from 1 to N. Then M lines follow, each
contains 3 integers, separated by a space: the numbers of two objects, and the length
of the spell to transform between them.
The input ends with N being 0. That case must NOT be processed.
Output Specification:
For each test case, output to the standard output. Print in one line the number of
the object which Harry must take to the exam, and the maximum length of the spell he
may have to say. The numbers must be separated by a space.
If it is impossible to complete all the transfigurations by taking one object only,
simply output 0. If the solution is not unique, output the one with the smallest
number.
Sample Input:
3 3
1 2 4
2 3 4
1 3 6
4 3
1 2 4
2 3 4
1 3 6
3 3
1 2 4
2 3 4
1 3 4
0 0
Sample Output:
2 4
0
1 4

My solution source code:

#include <iostream>
#include <queue>		//to create a priority queue
using namespace std;

const int Max_Vertex_Num=100;	//max number of vertex
const int Infinity=100000;		//define a Infinity number 	
int Ver_Num;					//global variable to save current vertex number;
		
///
//An adjacency list representation of an undirected
//representation of a undirected weighted graph
//
//edge node 
typedef struct EdgeNode{		
	int adjvex;					//other vertex of the edge
	int value;					//value of the edge			
	EdgeNode* next;				//next edge
}EdgeNode;						
typedef EdgeNode *Edge;

//vertex node
typedef struct VexNode{		    
   int No;					    //No. of vertex
   Edge next;				    //the head of adjlist
}VexNode,Graph[Max_Vertex_Num];
typedef VexNode* Vertex;

//to initialize the Grap with n node;
void Init_Graph(Graph G, int n)
{
    
	for (int i=0;i<n;i++){  //start from G[0],end at G[n-1]
       G[i].No=i+1;			//No of vertex 
       G[i].next=NULL;		//header of adjacency list
    }
 }
void Insert_Edge(Graph G,int i,int j,int edge)
{
	//insert edge between vertex i and j;
	Edge W,V;

	W=new(EdgeNode);	
	if(W==NULL)			//if can't allocate memory
	{
		cout<<"can't allocate memory! ";
		exit(1);
	}
	V=new(EdgeNode);
	if(V==NULL)//if can't allocate memory
	{
		cout<<"can't allocate memory! ";
		exit(1);
	}
	//insert W between G[i-1] and G[i-1].next
	W->next=G[i-1].next;			
	G[i-1].next=W;
	W->adjvex=j;		//set the adjvex to j
	W->value=edge;		//set the edge weight
	//insert V between G[j-1] and G[j-1].next
	V->next=G[j-1].next;
	G[j-1].next=V;
	V->adjvex=i;		//set the adjvex to j	
	V->value=edge;		//set the edge weight

}
//end of graph
///

typedef struct TableEntry
{
	Vertex Header;		//adjacency list's header
	bool Known;			//judge the vertex whether known 
	int dist;			//current distance to the start point
	int path;			//front vertex of current
	int curr_index;		//current index
}TableEntry,Table[Max_Vertex_Num];
//initialize the table by inputting a start point and a graph
void InitTable(int Start,Graph G,Table T)
{
	for(int i=0;i!=Ver_Num;i++)//traverse the table 
	{
		T[i].Header=&G[i];
		T[i].Known=false;
		T[i].dist=Infinity;	
		T[i].path=-1;		//not a vertex
		T[i].curr_index=i;	//current index
	}
	T[Start].dist=0;	//set the start point' distance to 0;
}
struct cmp
{
	bool operator()(const TableEntry& L,const TableEntry& R)
	{
		return L.dist>R.dist;
	}
};
typedef priority_queue<TableEntry,vector<TableEntry>,cmp> my_queue;
int Delete_Min(my_queue& Q)
{
	int res=Q.top().curr_index;
	Q.pop();
	return res;
}
//Dijstra algorithm to get the shortest path start table
void Dijkstra(Table T)
{
	int V,W;
	my_queue Q(T,T+Ver_Num);	//record table by priority queue
	while(!Q.empty())
	{ 
		V=Delete_Min(Q);//find smallest distance vertex and then remove from Q
		if(V<0)			//if not a vertex;
			 break;
		T[V].Known=true;
		Edge temp=T[V].Header->next; 
		for(;temp;temp=temp->next)//for each edge ajadency to V
		{
			W=temp->adjvex-1;
			if(!T[W].Known)
				if(T[V].dist+temp->value<T[W].dist)
				{//update  
					T[W].dist=T[V].dist+temp->value;
					T[W].path=V;
					Q.push(T[W]);		//record W in Q
				}
		}
	}
}


//find the max distance of table T
int Max_Dist_Of(Table T)
{
	int max=0;
	for(int j=0;j!=Ver_Num;j++)//travese
	{
		if(T[j].dist>max)
		{
			max=T[j].dist;
		}
	}
	return max;
}
int main()
{
	int N,M;
	cin>>N>>M;
	while(N)//when N is 0 ,break
	{
		Graph G;
		Init_Graph(G,N);	//initialize the graph

		int V,W,edge;
		for(int i=0;i!=M;i++)//insert edges
		{
			cin>>V>>W>>edge;
			Insert_Edge(G,V,W,edge);
		}
		Ver_Num=N;		//set current Ver_Num to N
		Table T;		
		int min=Infinity;	
		int min_No=0;
		for(int k=0;k!=Ver_Num;k++)//traverse the table
		{
			InitTable(k,G,T);		//initialize the table whose start point is k
			Dijkstra(T);			//get the shortest path start table
			int temp=Max_Dist_Of(T);//get the max distance of table T
			if(temp<min)  //find the smallest  of each table's max distance
			{
				min=temp;
				min_No=k+1;	//record the current No of vertex
			}
			
		}
		if(min<Infinity)//if exist solution
			cout<<min_No<<" "<<min<<endl;
		else			//if the graph is not connected
			cout<<0<<endl;
		cin>>N>>M;		//input next test case
	}
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值