Mr. Kitayuta‘s Technology CodeForces - 505D(並查集+拓撲排序或dfs找環) 題解
題目
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
3
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;
}
相關文章
- Codeforces-1131D:Gourmet choice(拓撲+並查集)Go並查集
- DFS實現拓撲排序排序
- 有向圖的拓撲排序——DFS排序
- 拓撲排序詳解(梅開二度之dfs版按字典序輸出拓撲路徑+dfs版輸出全部拓撲路徑排序
- 拓撲排序排序
- 拓撲排序,YYDS排序
- 拓撲排序 (BFS )DAG (有向無環圖)排序
- 圖論——拓撲排序圖論排序
- 筆記:拓撲排序筆記排序
- 拓撲排序小結排序
- 圖解拓撲排序+程式碼實現圖解排序
- Reward (圖論+拓撲排序)圖論排序
- AOV網與拓撲排序排序
- 【筆記/模板】拓撲排序筆記排序
- 圖的拓撲排序詳解與實現排序
- 拓撲排序就這麼回事排序
- 演算法-圖論-拓撲排序演算法圖論排序
- tidb拓撲查詢工具qtidbTiDBQT
- (set+拓撲排序) CF1572A Book排序
- 樹(tree) - 題解(帶權並查集)並查集
- [kuangbin帶你飛]專題五 並查集 題解並查集
- 並查集題目合集並查集
- 【題解】Solution Set - NOIP2024集訓Day8 並查集和可持久化並查集並查集持久化
- VOL.2 拓撲排序與關鍵路徑排序
- 【Tarjan 拓撲排序 dp】P3387 【模板】縮點排序
- CF771A. Bear and Friendship Condition 題解 並查集並查集
- Noc拓撲
- Codeforces2020D Connect the Dots(觀察 + 並查集 + 差分)並查集
- 專題五 並查集【Kuangbin】並查集
- 關於並查集問題並查集
- 洛谷P3953 逛公園(dp 拓撲排序)排序
- 牛客 51011 可達性統計(拓撲排序,bitset)排序
- HDD is Outdated Technology Codeforces 612B
- 並查集到帶權並查集並查集
- 一道很有趣的拓撲題
- 網路拓撲例項之RRPP單環(五)
- 【BZOJ-1565】植物大戰殭屍 拓撲排序 + 最小割排序
- 查並集