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;
}
相關文章
- hdu 1811 並查集+拓撲排序並查集排序
- DFS實現拓撲排序排序
- Codeforces-1131D:Gourmet choice(拓撲+並查集)Go並查集
- 有向圖的拓撲排序——DFS排序
- HDU 5438 Ponds (拓撲排序應用+DFS)排序
- 拓撲排序詳解(梅開二度之dfs版按字典序輸出拓撲路徑+dfs版輸出全部拓撲路徑排序
- hdu5222 拓撲+並查集並查集
- 拓撲排序排序
- codeforces 505C. Mr. Kitayuta, the Treasure Hunter (記憶化搜尋)
- 拓撲排序,YYDS排序
- 拓撲排序模板排序
- Codeforces 505C Mr. Kitayuta, the Treasure Hunter:dp【考慮可用範圍】
- 拓撲排序 (BFS )DAG (有向無環圖)排序
- 拓撲排序小結排序
- 圖論——拓撲排序圖論排序
- 筆記:拓撲排序筆記排序
- 圖解拓撲排序+程式碼實現圖解排序
- POJ1094[有向環 拓撲排序]排序
- Reward (圖論+拓撲排序)圖論排序
- 拓撲排序 - Topological Sort排序
- 拓撲排序核心程式碼排序
- HDU 4857 逃生(拓撲排序)排序
- 【筆記/模板】拓撲排序筆記排序
- AOV網與拓撲排序排序
- 圖的拓撲排序詳解與實現排序
- 拓撲排序就這麼回事排序
- HDU4857逃生(拓撲排序)排序
- 紙上談兵: 拓撲排序排序
- poj 1094 拓撲排序排序
- Codeforces Round #360 (Div. 1) D 並查集判奇環並查集
- poj1094 拓撲排序排序
- 演算法-圖論-拓撲排序演算法圖論排序
- 【圖論】拓撲排序+優先佇列圖論排序佇列
- POJ 3249-Test for Job(拓撲排序&&DP)排序
- CF 274D Lovely Matrix(拓撲排序)排序
- HDU 4857-逃生(反向拓撲排序-按條件排序)排序
- 排序(並查集&&雜湊函式)排序並查集函式
- 樹(tree) - 題解(帶權並查集)並查集