题目 
Shuseki Kingdom is the world’s leading nation for innovation and technology. There are n cities in the kingdom, numbered from 1 to n.

Thanks to Mr. Kitayuta’s research, it has finally become possible to construct teleportation pipes between two cities. A teleportation pipe will connect two cities unidirectionally, that is, a teleportation pipe from city x to city y cannot be used to travel from city y to city x. The transportation within each city is extremely developed, therefore if a pipe from city x to city y and a pipe from city y to city z are both constructed, people will be able to travel from city x to city z instantly.

Mr. Kitayuta is also involved in national politics. He considers that the transportation between the m pairs of city (ai, bi) (1 ≤ i ≤ m) is important. He is planning to construct teleportation pipes so that for each important pair (ai, bi), it will be possible to travel from city ai to city bi by using one or more teleportation pipes (but not necessarily from city bi to city ai). Find the minimum number of teleportation pipes that need to be constructed. So far, no teleportation pipe has been constructed, and there is no other effective transportation between cities.

Input 
The first line contains two space-separated integers n and m (2 ≤ n ≤ 105, 1 ≤ m ≤ 105), denoting the number of the cities in Shuseki Kingdom and the number of the important pairs, respectively.

The following m lines describe the important pairs. The i-th of them (1 ≤ i ≤ m) contains two space-separated integers ai and bi (1 ≤ ai, bi ≤ n, ai ≠ bi), denoting that it must be possible to travel from city ai to city bi by using one or more teleportation pipes (but not necessarily from city bi to city ai). It is guaranteed that all pairs (ai, bi) are distinct.

Output 
Print the minimum required number of teleportation pipes to fulfill Mr. Kitayuta’s purpose.

Example 
Input 
4 5 
1 2 
1 3 
1 4 
2 3 
2 4 
Output 

Input 
4 6 
1 2 
1 4 
2 3 
2 4 
3 2 
3 4 
Output 
4


题目大意就是城市之间可以修单向的瞬时传送门,现在给出需求(需要那个城市可以到达娜个城市),问你最少需要修多少个传送通道,首先可以知道,对于需求构成的一个联通块,若连通块有环,只需要把连通块里的点修出一个单项环,任意点就可以互相达到了,若无环,只需要修n-1条路就可以满足需求了。 
所以我们只需要用并查集找出所有的连通块,然后对每个连通块判断环就行,我用了拓扑排序和dfs找环两种方法来做。 
首先是拓扑排序,拓扑排序本身是针对无环有向图的,通过不断把没有入度的点入队来实现,而若有环,则环上的点始终无法入队,最后处理完它们的入度也不会变成零,这样就很容易找出环了。 
dfs找环的方法就是对点赋予状态,0表示没访问过,1表示这个点及其相连的连通块都已经访问过了,-1则表示这个点正在对其dfs深搜访问,若一个点状态为-1又被再一次访问到,那么这肯定就是一个环了。

1.拓扑排序

#include<iostream>
#include<string.h>
#include<stdio.h>
#include<string>
#include<vector>
#include<algorithm>
#include<queue>
#include<set>
#include<stack>
using namespace std;
int f[100005];
int n, m;
vector<int > e[100005];
queue<int> que;
int F(int x){if (f[x] == x)return x;return f[x] = F(f[x]); }
bool H[100005];
int lt[100005];
bool vis[100005];
int deg[100005];void func(){while (!que.empty()){int cnt = que.front();que.pop();for (int i = 0; i < e[cnt].size(); i++){deg[e[cnt][i]]--;if (deg[e[cnt][i]] == 0)que.push(e[cnt][i]);}}
}int main(){int x, y;scanf("%d%d", &n, &m);for (int i = 1; i <= n; i++)f[i] = i;for (int i = 0; i < m; i++){scanf("%d%d", &x, &y);e[x].push_back(y);deg[y]++;f[F(x)] = F(y);}for (int i = 1; i <= n; i++){lt[F(i)]++;if (deg[i] == 0)que.push(i);}func();int ans = 0;for (int i = 1; i <= n; i++){if (deg[i] != 0)H[F(i)] = 1;}for (int i = 1; i <= n; i++){if (f[i] == i){if (H[i])ans += lt[i];else{ ans += lt[i] - 1; }}}printf("%d", ans);return 0;
}

2.DFS找环

#include<iostream>
#include<string.h>
#include<stdio.h>
#include<string>
#include<vector>
#include<algorithm>
#include<queue>
#include<set>
#include<stack>
using namespace std;
int f[100005];
int n, m;
vector<int > e[100005];
queue<int> que;
int F(int x){if (f[x] == x)return x;return f[x] = F(f[x]); }
bool H[100005];
int lt[100005];
bool vis[100005];
int c[100005];void dfs(int cnt){c[cnt] = -1;for (int i = 0; i < e[cnt].size(); i++){int cur = e[cnt][i];if (c[cur] == -1){ H[F(cur)] = 1; break; }else if (c[cur] == 0){ dfs(cur); }}c[cnt] = 1;
}int main(){int x, y;scanf("%d%d", &n, &m);for (int i = 1; i <= n; i++)f[i] = i;for (int i = 0; i < m; i++){scanf("%d%d", &x, &y);e[x].push_back(y);//deg[y]++;f[F(x)] = F(y);}for (int i = 1; i <= n; i++){lt[F(i)]++;if (c[i] == 0)dfs(i);//if (deg[i] == 0)que.push(i);}
//  func();int ans = 0;for (int i = 1; i <= n; i++){if (f[i] == i){if (H[i])ans += lt[i];else{ ans += lt[i] - 1; }}}printf("%d", ans);return 0;
}

Mr. Kitayuta‘s Technology CodeForces - 505D(并查集+拓扑排序或dfs找环) 题解相关推荐

  1. 【CF#505B】Mr. Kitayuta's Colorful Graph (并查集或Floyd或BFS)

    题干: Mr. Kitayuta has just bought an undirected graph consisting of n vertices and m edges. The verti ...

  2. hdu 1811 Rank of Tetris (并查集+拓扑排序)

    Problem - 1811 感觉这题的并查集以及拓扑排序并不难,但是做题的时候必须理解到矛盾(CONFLICT)与不确定(UNCERTAIN)直接的优先关系. 做这题的时候,构图什么的很简单,就是没 ...

  3. hdu 1811Rank of Tetris (并查集 + 拓扑排序)

    1 /* 2 题意:这些信息可能有三种情况,分别是"A > B","A = B","A < B",分别表示A的Rating高于B ...

  4. HDU——1272小希的迷宫(并查集+拓扑排序)

    小希的迷宫 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Subm ...

  5. 家谱树 (并查集拓扑排序)

    目录 拓扑排序 Kahn. 最后附上Kahn的代码: 链式前向星做法: 其次是我用Kahn做的家谱树的代码(矩阵): 其次是我用Kahn做的家谱树的代码(链式前向星): [题目描述] 有个人的家族很大 ...

  6. hdu5222 Exploration【并查集+拓扑排序】

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5222 题意:有一个探险家,探险一个地方,这个地方有n个洞穴,有若干条边,有的边是有向边,有的是无向边, ...

  7. CodeForces - 1463E Plan of Lectures(拓扑排序+并查集缩点)

    题目链接:点击查看 题目大意:给出一棵有根树,树边都是有向边,再给出 kkk 个关系 (x,y)( x , y )(x,y),其意义是访问完点 xxx 后需要立即访问点 yyy,问是否存在一种合适的拓 ...

  8. Codeforces 827D Best Edge Weight 倍增 + 并查集 || 倍增 + 压倍增标记 (看题解)

    Best Edge Weight 我们先找出一棵最小生成树, 对于非树边来说, 答案就是两点路径上的最大值 - 1, 这个直接倍增就能处理. 对于树边来说, 就是非树边的路径经过这条边的最小值 - 1 ...

  9. A - Cthulhu CodeForces - 103B (并查集)

    -Once upon a time a man came to the sea. The sea was stormy and dark. The man started to call for th ...

最新文章

  1. JOptionPane提示框的一些常用方法
  2. python -- 环境搭建
  3. 树分治树链剖分相关题目讨论
  4. js RegExp正则表达式常见用例
  5. asp.net使用post方式action到另一个页面,在另一个页面接受form表单的值!(报错,已解决!)...
  6. 【转】Net Framework,Net Core 和 Net Standard 区别
  7. 如何使用KingShard构建MySQL集群
  8. oracle 锁表 and 解锁
  9. Nginx应用场景之HTTP服务器
  10. 一步一步学Ruby(二):变量,常量
  11. 苹果手机时区改不了怎么办_苹果日期和时间怎么修改不了
  12. Mybatis_day4_Mybatis的注解开发
  13. System类的概述和方法使用
  14. 用getchar和%C输入字符型数据
  15. 389. Find the Difference
  16. python3 下载网络图片
  17. 使用引导扇区维护工具BOOTICE编辑系统启动列表BCD文件
  18. 计算机课程设计心得,课程设计心得体会450字
  19. 手机app网易邮箱服务器设置,网易邮箱默认开通IMAP服务
  20. Nuc做文件服务器,Intel NUC 安装Windows Server 2016 图解教程

热门文章

  1. VMWare 环境下devstack创建虚拟机报错及修改nova-api返回数据得条目
  2. [hackinglab][CTF][基础关][2020] hackinglab 基础关 writeup
  3. [Leedcode][JAVA][第67题][二进制求和][位运算][字符串]
  4. Java集合容器面试题
  5. 二维凸包 Graham's Scan
  6. Java学习笔记7-2——注解与反射
  7. java收发邮寄_JavaMail收发邮件的一般流程与主要方法
  8. 康宁玻璃ct值计算公式_【钦州】CT室铅板生产厂家
  9. 华为swot分析2020_科技口译现场:华为2020全球分析师大会
  10. php 方法里用外部变量的值,PHP实现函数内修改外部变量值的方法示例