搜索专题题解

题目链接:

  codeforces 277A - Learning Languages

题目描述:

  一个团体有n个人,每个人都掌握了一些语言,每个人学一门语言有1个花费,两个人之间可以通过其他人的翻译,问最少花费多少使得这个团体的任意两个人都可以交流?

解题思路:

  可以bfs,dfs求连通块,也可以用并查集求集合数目。(PS:唯一要注意的是当每一个人都是只会0种语言,辣么每个人是不是都要学习语言,特判一下就好辣)

 搜索专题,先贴dfs代码咯~

 1 #include <bits/stdc++.h>

 2 using namespace std;

 3 const int maxn = 205;

 4 struct Edge//邻接表建图,dfs求连通块数目

 5 {

 6     int to, next;

 7 };

 8 

 9 Edge edge[maxn*maxn];

10 int head[maxn], vis[maxn], tot;

11 

12 void Add (int from, int to)

13 {

14     edge[tot].to = to;

15     edge[tot].next = head[from];

16     head[from] = tot ++;

17 }

18 void dfs (int x)

19 {

20     vis[x] = 1;

21     for (int i=head[x]; i!=-1; i=edge[i].next)

22         if (!vis[edge[i].to])

23             dfs (edge[i].to);

24 }

25 

26 int main ()

27 {

28     int n, m;

29     while (scanf ("%d %d", &n, &m) != EOF)

30     {

31         int k, num, sum = 0;

32         tot = 0;

33         memset (head, -1, sizeof(head));

34         memset (edge, 0, sizeof(edge));

35         memset (vis, 0, sizeof(vis));

36         for (int i=0; i<n; i++)

37         {

38             scanf ("%d", &k);

39             sum += k;

40             while (k --)

41             {

42                 scanf ("%d", &num);

43                 Add (i, num+n-1);

44                 Add (num+n-1, i);

45             }

46         }

47         num = 0;

48         for (int i=0; i<n; i++)

49             if (!vis[i])

50             {

51                 dfs(i);

52                 num ++;

53             }

54         if (sum)

55             num --;

56         printf ("%d\n", num);

57     }

58     return 0;

59 }
View Code

 

再贴一个并查集代码

 1 #include <bits/stdc++.h>

 2 using namespace std;

 3 const int maxn = 205;

 4 int father[maxn], n, m;

 5 

 6 void init ()

 7 {

 8     for (int i=0; i<maxn; i++)

 9         father[i] = i;

10 }

11 int find (int x)

12 {

13     if (father[x] != x)

14         father[x] = find (father[x]);

15     return father[x];

16 }

17 int main ()

18 {

19     while (scanf ("%d %d", &n, &m) != EOF)

20     {

21         init ();

22         int k, x, ans = 0;

23         for (int i=1; i<=n; i++)

24         {

25             scanf ("%d", &k);

26             if (k)

27                 ans = -1;

28             while (k --)

29             {

30                 scanf ("%d", &x);

31                 int pi = find(i);

32                 int px = find(x+n);

33                 if (pi != px)

34                     father[px] = father[pi];

35             }

36         }

37         for (int i=1; i<=n; i++)

38             if (father[i] == i)

39             ans ++;

40         printf ("%d\n", ans);

41     }

42     return 0;

43 }
View Code

 

题目链接:

  codeforce 520B - Two Buttons

题目描述:

  有n,m两个数,现有两种操作:

    1:n可以*2;2:n可以减1。问最少操作多少次可以使n==m?

解题思路:

  这次是最优解,又是搜索专题,肯定是bfs咯,tle的估计就是vis数组出问题咯,还有要注意n,m的范围哟!

还是先贴bfs代码

 1 #include <bits/stdc++.h>

 2 using namespace std;

 3 const int maxn = 10005;

 4 struct node

 5 {

 6     int x, step;

 7 };

 8 int bfs (int n, int m)

 9 {

10     node p, q;

11     queue <node> Q;

12     int vis[maxn];

13     memset (vis, 0, sizeof(vis));

14     vis[n] = 1;

15     p.x = n;

16     p.step = 0;

17     Q.push (p);

18     while (!Q.empty())

19     {

20         p = Q.front();

21         Q.pop();

22         if (p.x == m)

23             return p.step;

24         q.step = p.step + 1;

25         int x = p.x - 1;

26         int y = p.x * 2;

27         if (x > 0 && !vis[x])

28         {

29             q.x = x;

30             Q.push (q);

31             vis[x] = 1;

32         }

33         if (p.x<m && y<maxn && !vis[y])

34         {

35             q.x = y;

36             Q.push (q);

37             vis[y] = 1;

38         }

39     }

40 }

41 int main ()

42 {

43     int n, m;

44     while (scanf ("%d %d", &n, &m) != EOF)

45         printf ("%d\n", bfs(n, m));

46     return 0;

47 }
View Code

再贴一个代码,这个代码简单易懂

 1 /*这个要进行逆向思维

 2   这时候要考虑把m-->n

 3   两种操作就变成了m/2与m+1

 4   当m>n的时候只能进行+1操作

 5   当m<n的时候只能进行/2操作(要讨论m的奇偶性)

 6   循环操作,m==n的时候就一切ok啦

 7 */

 8 #include <bits/stdc++.h>

 9 using namespace std;

10 const int maxn = 10005;

11 int main ()

12 {

13     int n, m, ans;

14     while (scanf ("%d %d", &n, &m) != EOF)

15     {

16         ans = 0;

17         while (true)

18         {

19             if (m <= n)

20             {

21                 ans += n - m;

22                 break;

23             }

24             if (m%2)

25             {

26                 m ++;

27                 ans ++;

28             }

29             m /= 2;

30             ans ++;

31         }

32         printf ("%d\n", ans);

33     }

34     return 0;

35 }
View Code

这两个题目都可以用其他方法做,完美的避开了搜索,不知道会不会对小学弟(美)们造成误导哦,还是声明一下搜索很重要的,搜索很重要的,搜索很重要的(重要的事情说三遍)。是很多其他算法的基础。

你可能感兴趣的:(搜索)