现在的位置: 首页 > 综合 > 正文

NYOJ-20 吝啬的国度

2017年12月19日 ⁄ 综合 ⁄ 共 2264字 ⁄ 字号 评论关闭

吝啬的国度

时间限制: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

无环无向图,寻找某点到所有其它点的最短路径。一开始用的dijkstra,超时,后来改成深度搜索就好了,广度搜索也能做。由于N过大,所以用邻连矩阵表示图的连接情况,太耗空间,所以这里用邻接表。

#include
<stdio.h>
02.#include
<vector>
03.#include
<string.h>
04.using namespace std;
05. 
06.#define
MAXN 100005
07. 
08.int path[MAXN],vis[MAXN];
09. 
10.vector<
vector<
int>
> v;
11. 
12.void dfs(int k)
13.{
14.vis[k]=1;
15.vector<int>::iterator
it=v[k].begin();
16.for(;it!=v[k].end();it++)
17.{
18.if(vis[*it]==0)
19.{
20.path[*it]=k;
21.dfs(*it);
22.}
23.}
24.}
25. 
26.int main()
27.{
28.int M,N,S,a,b;
29.scanf("%d",&M);
30.while(M--)
31.{
32.scanf("%d%d",&N,&S);
33.v.resize(N+1);
34.for(int i=0;i<N-1;i++)
35.{
36.scanf("%d%d",&a,&b);
37.v[a].push_back(b);
38.v[b].push_back(a);
39.}
40.memset(vis,0,sizeof(vis));
41.dfs(S);
42.path[S]=-1;
43.for(int i=1;i<N;i++)
44.printf("%d
"
,path[i]);
45.printf("%d\n",path[N]);
46.v.clear();
47.}
48.return 0;
49.}

上面的是正常思路,耗时还是挺多的,该算法耗时260ms,当时平台排第一的算法耗时只有36ms。内存也用得少了。

下面的算法思路基本是这样的(我的理解):map[a]=b,可以理解为b是a的父亲。

当输入a,b时,如果b没有父亲,就让a作为b的父亲;

如果b已经有父亲了,那就调整a,让a的父亲,a的父亲的父亲…关系颠倒,即让map[a]=a1,map[a1]=map[a2]…变成map[a2]=a1,map[a1]=a,这样a是其子孙的父亲,然后让b成为a的父亲

上面这两步,主要作用就是让所有节点间的关系是成单向的。这样,最后只要对S节点进行上述的颠倒调整就可以了。

#include
<stdio.h> 
02.#include
<memory.h>  
03.int map[100005]; 
04. 
05.void Adjust(int currentCity) 
06.
07.int priorCity
= map[currentCity]; 
08.if (priorCity
!= 0) 
09.
10.Adjust(priorCity); 
11.map[priorCity]
= currentCity; 
12.
13.
14. 
15. 
16.int main() 
17.
18.int i,
n, m, s, A, B; 
19.scanf("%d",
&n); 
20.while (n--) 
21.
22. 
23. 
24.scanf("%d%d",
&m, &s); 
25. 
26. 
27.memset(map,
0, 
sizeof(map)); 
28. 
29. 
30.// 
for(i=0;i<20;i++)
31.// 
printf("%d ",map[i]);
32. 
33. 
34.for (i
= 1; i < m; i++) 
35.
36.scanf("%d%d",
&A, &B); 
37. 
38. 
39.if (map[B]
== 0) 
40.map[B]
= A;  
41.else 
42.
43.Adjust(A); 
44.map[A]
= B; 
45.}
46.// 
printf("**************%d \n",map[A]);
47.}
48. 
49. 
50.Adjust(s); 
51.map[s]
= - 1; 
52. 
53. 
54. 
55. 
56.for (i
= 1; i <=m; i++) 
57.printf("%d
"
,
map[i]); 
58. 
59.printf("\n"); 
60.
61.return 0; 
62.}

抱歉!评论已关闭.