• 解题笔记——NIT 遥远的村庄


    某个小镇有 N 个村庄,村庄编号1-N,给出 M 条单向道路,不存在环,即不存在 村庄A可以到达村庄B 且 村庄B也可以到达村庄A的情况。
    如果村庄A与村庄B之间存在一条单向道路,则说村庄A和村庄B之间存在联系,联系具有无向性,即如果村庄A和村庄B有联系,则村庄B和村庄A有联系;联系具有传递性,即如果存在村庄A和村庄B有联系,村庄B和村庄C有联系,则村庄A和村庄C有联系。
    现在小镇要在某些村庄里建垃圾站,对建垃圾站的村庄要满足与之有联系的村庄都可以通过单向道路到达该村庄。问小镇能建多少个垃圾站。

     

    Input

    输入包含多组数据,对于每组数据:
    第一行输入N,M,数据范围1<=n<=1000,0<=m<10000。
    接下来M行,每行两个整数,s,t,代表 s 可以到达 t 。

     

    Output

    对于每组数据,输出一个整数代表答案。

     

    Sample Input

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

    Sample Output

    4

    Hint

    案例中有10个村庄,道路情况如下:

    1->2->3->4

    5

    6->7->8

    9->10

    村庄4可以建垃圾站,因为与之有联系的村庄都能到达他;同理村庄5,村庄8,村庄10,所以答案有4个。

    解题思路:

    要建垃圾站的话,该村庄所在的关于村庄联系的联通块内的结点数和他的单向道路能到达的结点数相同,但是建边要反向建,本来u到v的边要建成v到u的边,用并查集算各个联通块内结点数,然后dfs算能到达多少个结点再跟该联通块内结点总数比较,相等的话说明可以建垃圾站

    难点在看不懂题意

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 typedef long long ll;
     4 typedef unsigned long long ull;
     5 #define INF 0x3f3f3f3f
     6 const ll MAXN = 1e3 + 7;
     7 const ll MAXM = 1e4 + 7;
     8 const ll MOD = 1e9 + 7;
     9 const double pi = acos(-1);
    10 int n, m;
    11 int vis[MAXN];
    12 int pre[MAXN];
    13 vector<int> V[MAXN];
    14 int root[MAXN]; //根结点的位置记录联通块内结点数
    15 int cnt;
    16 void init()
    17 {
    18     memset(vis, 0, sizeof(vis));
    19     memset(root, 0, sizeof(root));
    20     for (int i = 1; i <= n; i++)
    21         pre[i] = i, V[i].clear();
    22 }
    23 int find(int x) //查找根结点
    24 {
    25     int r = x;
    26     while (r != pre[r]) //寻找根结点
    27         r = pre[r];
    28     int i = x, j;
    29     while (pre[i] != r) //路径压缩
    30     {
    31         j = pre[i];
    32         pre[i] = r;
    33         i = j;
    34     }
    35     return r;
    36 } //并查集求联通块块数
    37 //遍历有向图结点
    38 void DFS(int u)
    39 {
    40     cnt++;
    41     vis[u] = 1;
    42     for (int i = 0; i < V[u].size(); i++)
    43     {
    44         int v = V[u][i];
    45         if (!vis[v])
    46         { //如果该节点未被访问,则深度遍历
    47             DFS(v);
    48         }
    49     }
    50 }
    51 int main()
    52 {
    53     while (~scanf("%d%d", &n, &m))
    54     {
    55         init();
    56         int ans = 0;
    57         for (int i = 0; i < m; i++)
    58         {
    59             int u, v;
    60             scanf("%d%d", &u, &v);
    61             V[v].push_back(u);
    62             int fa = find(u);
    63             int fb = find(v);
    64             if (fa != fb)
    65                 pre[fa] = fb;
    66         }
    67         for (int i = 1; i <= n; i++)
    68             root[find(i)]++;
    69         for (int i = 1; i <= n; i++)
    70         {
    71             memset(vis, 0, sizeof(vis));
    72             cnt = 0;
    73             DFS(i);
    74             if (cnt == root[find(i)])
    75                 ans++;
    76         }
    77         printf("%d
    ", ans);
    78     }
    79     return 0;
    80 }
    81 /* 14 7
    82 1 8
    83 2 8
    84 4 5
    85 7 8
    86 9 7
    87 6 7
    88  6 8
    89 */

     

  • 相关阅读:
    Ubuntu18.04彻底删除MySQL数据库(转载)
    Windows中杀死占用某个端口的进程(转载)
    记一次使用mybatis生成工具生成mapper层代码
    解决git push过程中出现Please make sure you have the correct access rights and the repository exists.(转载)
    xshell连接到Vmware中的centos附加解决ens33看不到ip地址的问题
    常见Git命令清单(转载)
    Linux常用命令大全(转载)
    腾讯云centos服务器上安装hadoop踩坑记
    PowerShell 获取大文件行数
    Cannot Login to SQL Server using administrator account
  • 原文地址:https://www.cnblogs.com/graytido/p/10846632.html
Copyright © 2020-2023  润新知