吝啬的国度
时间限制: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 }
时间: 2024-10-21 22:24:28