zoukankan      html  css  js  c++  java
  • 搜索专题题解

    题目链接:

      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
    ", 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
    ", 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
    ", 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
    ", ans);
    33     }
    34     return 0;
    35 }
    View Code

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

    ————————————————————————————————————我是邪魅温柔的分割线——————————————————————————————

    题目链接:

      Codeforces 445B - DZY Loves Chemistry

    题目描述:

      n种试剂,m种反应(反应发生在两种试剂之间),DZY想要把这n种试剂混合,DZY依次向试管中加入试剂,刚开始试管的危险系数为1,如果当前所需要加入的试剂能与试管中的某种试剂反应,则试管的危险系数乘二,现在为了安全起见,问试管最高的危险系数是多少?

    解题思路:

      很裸地并查集嘛!因为最终的状态肯定是所有的试剂都在试管里面,只需要知道每个集合里面元素个数就OK啦!!

     1 #include <queue>
     2 #include <cstdio>
     3 #include <cstring>
     4 #include <iostream>
     5 #include <algorithm>
     6 using namespace std;
     7 typedef __int64 LL;
     8 const int maxn = 100;
     9 int father[maxn];
    10 void init ()
    11 {
    12     for (int i=0; i<maxn; i++)
    13         father[i] = i;
    14 }
    15 int Find(int x)
    16 {
    17     if (x != father[x])
    18         father[x] = Find(father[x]);
    19     return father[x];
    20 }
    21 int main ()
    22 {
    23     int n, m;
    24     while (scanf ("%d %d", &n, &m) != EOF)
    25     {
    26         init ();
    27         LL ans = 1;
    28         while (m --)
    29         {
    30             int x, y;
    31             scanf ("%d %d", &x, &y);
    32             int px = Find (x);
    33             int py = Find (y);
    34             if (px != py)
    35             {
    36                 father[px] = py;
    37                 ans *= 2;
    38             }
    39         }
    40         printf ("%I64d
    ", ans);
    41     }
    42     return 0;
    43 }
    本文为博主原创文章,未经博主允许不得转载。
  • 相关阅读:
    实验一 命令解释程序的编写
    试验二
    实验一 命令解释程序的编写(重交)
    Sqlserver数据库帮助类(EFTools)
    js验证
    sqlserver中从日期字段取得月份
    IIS不可用或者有问题解决方法
    professional email address collections
    从psd文件到html
    空白符对HTML结构的影响与解决方案
  • 原文地址:https://www.cnblogs.com/alihenaixiao/p/4653579.html
Copyright © 2011-2022 走看看