NYOJ -20-吝啬的国度

吝啬的国度

时间限制:1000 ms  |  内存限制:65535 KB
 
难度:3

描述在一个吝啬的国度里有N个城市,这N个城市间只有N-1条路把这个N个城市连接起来。现在,Tom在第S号城市,他有张该国地图,他想知道如果自己要去参观第T号城市,必须经过的前一个城市是几号城市(假设你不走重复的路)。

 

输入第一行输入一个整数M表示测试数据共有M(1<=M<=5)组
每组测试数据的第一行输入一个正整数N(1<=N<=100000)和一个正整数S(1<=S<=100000),N表示城市的总个数,S表示参观者所在城市的编号
随后的N-1行,每行有两个正整数a,b(1<=a,b<=N),表示第a号城市和第b号城市之间有一条路连通。输出每组测试数据输N个正整数,其中,第i个数表示从S走到i号城市,必须要经过的上一个城市的编号。(其中i=S时,请输出-1)样例输入

1 10 1 1 9 1 8 8 10 10 3 8 6 1 2 10 4 9 5 3 7

样例输出

-1 1 10 10 9 8 3 1 1 8

 

 

 之所以特别的记录下这道题,源于作为小菜的我,发现我一直认为需要BFS的题被大神用很简单的代码搞定,并且时间内存皆远远胜之。

花了半个多小时,才理解了大神的思路,真是太妙了!

剖析题意,从输入数据中可以得到各个城市之间的无向图(因为双向),而我们需要得到的是一个以s城市为起点的有向图。

我们用mp[i]来表示从s到i号城市必须经过的上一个城市编号。

为了更形象的描述,我们在这里 将 mp[a]=b  称为 b指向a  显然,每个节点智能被一个城市指向(否则无法保存嘛)

初始化 mp[i]=0;

则对于每组边的两节点 a,b  

     若mp[b]=0,即无城市指向b,则令a指向b:mp[b]=a

     若mp[b]!=0, 即已经有城市指向b,那么,这时当然要将b指向a,即mp[a]=b;

          然而,我们并不知道是否有城市指向a,若有 则mp[a]!=0 ,上述操作会将此值覆盖

          所以,在此之前,我们需要将所有指向a的城市节点,方向调换,即若t指向a,则改为a指向t

          同时,再以t为起始递归下去,这样就可以让已a为起点的一系列有向线路全部转换方向,实现180转弯。

     经过上述操作我们已经得到一个有向图,但仍然不能满足题目要求,因为起点是s,故每个有向线路的起点必然是由s开始的,

      所以,我们对s点,进行上述的递归操作,此时,任务完成,所有的有向路都是已s点为出发点的了。

代码如下:

 

 

 1 #include<string.h>

 2 #include<stdio.h>

 3 #include<stdlib.h>

 4 

 5 

 6 int m,n,s,mp[100005];  7 

 8 void def(int s)  9 { 10     int t=mp[s]; 11     if(t!=0) 12  { 13  def(t); 14         mp[t]=s; 15  } 16 } 17 

18 int main(void) 19 { 20     scanf("%d",&m); 21     while(m--) 22  { 23         int a,b; 24         scanf("%d%d",&n,&s); 25         memset(mp,0,sizeof(int)*n+1); 26         for(int i=1;i<n;i++) 27  { 28             scanf("%d%d",&a,&b); 29             if(mp[a]==0) 30  { 31                 mp[a]=b; 32  } 33             else

34  { 35  def(b); 36                 mp[b]=a; 37  } 38  } 39  def(s); 40         mp[s]=-1; 41         for(int i=1;i<=n;i++) 42  { 43             printf("%d ",mp[i]); 44  } 45         printf("\n"); 46  } 47     return 0; 48 }

 

你可能感兴趣的:(OJ)