/*
习题 54: 邮递员★★★
题目描述:
有一个邮递员要在n个城市之间来回送信。但有的城市之间有大路相连
而有的没有路。现在要由一个城市到另一个城市送信,中途最少要经过
多少个其它的城市呢?
输入:
第一行是n,k(1<=n<=10000, 1<=k<=20000),接下来就是k行。
这k行每行有两个数a,b(1 <= a,b <= n),表示城市a和b之间有大路
k行以后就是两个数p和q。
当n,k输入都为0的时候结束。
输出:
输出从城市p到城市q之间最少要经过的其它的城市的数目。
如果p和q之间不连通则输出"No solution"
样例输入:
6 6
1 4
1 2
2 3
3 4
5 4
5 6
1 6
0 0
样例输出:
2
难度:Normal
*/
#include "StdAfx.h"
#include <iostream>
#include <cassert>
#define MAX_DIRECTION 40000 //总共可能有40000条有向路线
#define MAX_CITY_NUMS 10001 //邻接表表头数量
#define QUEUE_SIZE 10001 //队列容量
#define TABLE_SIZE 10001 //表容量
#define UNVISITED 0 //未访问节点,但是对应节点的距离可以是已知的
#define VISITED 1
//分配节点
//#define MALLOC_NODE(p) (p) = &space[CityNodeCount++]
#define INFINITY 1001 //无穷远
//临接矩阵用
typedef struct adjacent
{
int city_num;
struct adjacent *next;
} CityNode;
//全局数组,模拟heap,降低系统开销
CityNode space[MAX_DIRECTION];
//space用掉了多少空间;
int CityNodeCount;
//邻接表表头
CityNode head[MAX_CITY_NUMS];
//邻接表中实际节点个数
int real_city_num;
//节点队列
CityNode* queue[QUEUE_SIZE];
int queue_head,queue_end;
//无权最短路径配置表
int table[TABLE_SIZE][2];//known, dv, pv(discard)
void initialize(int n)
{
int i;
CityNodeCount = 0;
real_city_num = n;
//memset(head, 0, MAX_CITY_NUMS * sizeof(void(*)));//初始化邻接表表头
for( i = 0; i < MAX_CITY_NUMS;)
{
head[i].next = NULL;
head[i].city_num = ++i;
}
memset(queue, 0, QUEUE_SIZE * sizeof(void(*)));//初始化队列
queue_head = queue_end = 0;
memset(space, 0, MAX_DIRECTION * sizeof(CityNode));// 初始化heap
for(i = -1; ++i < TABLE_SIZE;)
{
table[i][0] = UNVISITED; //known
table[i][1] = INFINITY; //distance from start point
//table[i][2] = 0; //previous point,discard
}
}
//将数据插入邻接表
void insert_adjacent(int city_start, int city_end)
{
CityNode *tmp;
tmp = head[city_start].next;
//MALLOC_NODE(head[city_start]);
head[city_start].next = &space[CityNodeCount++];
head[city_start].next->next = tmp;
//assert(head[city_start] == &space[CityNodeCount - 1]);
head[city_start].next->city_num = city_end;
tmp = head[city_end].next;
//MALLOC_NODE(head[city_end]);
head[city_end].next = &space[CityNodeCount++];
head[city_end].next->next = tmp;
head[city_end].next->city_num = city_start;
}
//搜索并输出结果
void search(int start_city, int end_city)
{
int cur_distance;
CityNode *tmp;
tmp = &head[start_city];
queue[queue_end++] = tmp;
if(start_city == end_city)
{
printf("%d/n",0);
return;
}
/*
table[start_city][0] = VISITED;*/
table[start_city][1] = 0;//distance
cur_distance = 0;
//printf("search entered!first city is %d/n",start_city);
do
{
tmp = queue[queue_head];
//printf("%d out queue/n",tmp->city_num);
queue[queue_head] = NULL;
queue_head =(queue_head + 1) % QUEUE_SIZE;
table[tmp->city_num][0] = VISITED;//known
//table[tmp->city_num][1] = cur_distance;
cur_distance = table[tmp->city_num][1] + 1;
tmp = tmp->next;
while(tmp)//adjacent
{
//printf("city %d->",tmp->city_num);
if(table[tmp->city_num][1] == INFINITY)
{
//if(table[tmp->city_num][1] == INFINITY)
table[tmp->city_num][1] = cur_distance;//distance
//enqueue
queue[queue_end] = &head[tmp->city_num];
//printf("/n city %d enqueue /n",tmp->city_num);
queue_end = (queue_end + 1) % QUEUE_SIZE;
}
tmp = tmp->next;
}
//printf("/nqueue_head = %d,queue_end = %d/n",queue_head,queue_end);
if(queue_head == queue_end)
break;
else
continue;
} while (true);
//printf("search end!/n");
if(INFINITY == table[end_city][1])
{
printf("No solution/n");
}else
{
printf("%d/n",table[end_city][1]-1);
}
//printf("out search!/n");
}
int main(void)
{
int n,k,j;
int city_start, city_end;
while(scanf("%d%d",&n,&k)!=EOF)
{
if(n == 0 && k == 0)
break;
initialize(n);
for(j = -1; ++j < k;)
{
//printf("process 0/n");
scanf("%d%d",&city_start,&city_end);
//printf("process 1/n");
insert_adjacent(city_start,city_end);
//printf("process 2/n");
}
scanf("%d%d",&city_start,&city_end);
search(city_start,city_end);
}
return 0;
}
/*
79690
Submit Time: 2008/10/03-09:01
G++: Compile OK
Test 1: Accepted Time = 0 ms
Test 2: Accepted Time = 0 ms
Test 3: Accepted Time = 10 ms
--------------------------------
Problem ID 54
Test Result Accepted
Total Time 10 ms
Total Memory 668 Kb / 2000 Kb
Code Length 2725 Bytes
*/