New Reform
题目描述
Berland has n n n cities connected by m m m bidirectional roads. No road connects a city to itself, and each pair of cities is connected by no more than one road. It is not guaranteed that you can get from any city to any other one, using only the existing roads.
The President of Berland decided to make changes to the road system and instructed the Ministry of Transport to make this reform. Now, each road should be unidirectional (only lead from one city to another).
In order not to cause great resentment among residents, the reform needs to be conducted so that there can be as few separate cities as possible. A city is considered separate, if no road leads into it, while it is allowed to have roads leading from this city.
Help the Ministry of Transport to find the minimum possible number of separate cities after the reform.
输入格式
The first line of the input contains two positive integers, n n n and m m m — the number of the cities and the number of roads in Berland ( 2 < = n < = 100000 2<=n<=100000 2<=n<=100000 , 1 < = m < = 100000 1<=m<=100000 1<=m<=100000 ).
Next m m m lines contain the descriptions of the roads: the i i i -th road is determined by two distinct integers x i , y i x_{i},y_{i} xi,yi ( 1 < = x i , y i < = n 1<=x_{i},y_{i}<=n 1<=xi,yi<=n , x i ≠ y i x_{i}≠y_{i} xi=yi ), where x i x_{i} xi and y i y_{i} yi are the numbers of the cities connected by the i i i -th road.
It is guaranteed that there is no more than one road between each pair of cities, but it is not guaranteed that from any city you can get to any other one, using only roads.
输出格式
Print a single integer — the minimum number of separated cities after the reform.
提示
In the first sample the following road orientation is allowed: ,
,
.
The second sample: ,
,
,
,
.
The third sample: ,
,
,
,
.
题面翻译
题目描述
有 n n n 个城市, m m m 条双向道路,没有一个城市存在自己到自己的道路,两个不同的城市间,最多有一条道路,也不能保证能从一个城市到达任意一个其他城市。
现在需要对每一条道路定向,使之成为单向道路,当然需要尽可能少地产生孤立的城市。当其他所有城市都不能到达某个城市,则称这个城市为孤立城市。要求出最少的孤立城市的个数。
输入格式
第一行,两个整数, n n n 和 m m m。
接下来 m m m 行,每行两个整数 x i x_i xi 和 y i y_i yi,表示一条道路连接城市 x i x_i xi 和城市 y i y_i yi 的双向道路。
输出格式
一行,一个整数,表示最少的孤立城市的个数。
数据规模与约定
2 ≤ n ≤ 100000 2\le n\le 100000 2≤n≤100000, 1 ≤ m ≤ 100000 1\le m\le 100000 1≤m≤100000。
对于每一个合法的 x i x_i xi 和 y i y_i yi,都有 1 ≤ x i , y i ≤ n 1\le x_i,y_i\le n 1≤xi,yi≤n,且 x i ≠ y i x_i ≠ y_i xi=yi。
样例 #1
样例输入 #1
4 3
2 1
1 3
4 3
样例输出 #1
1
样例 #2
样例输入 #2
5 5
2 1
1 3
2 3
2 5
4 3
样例输出 #2
0
样例 #3
样例输入 #3
6 5
1 2
2 3
4 5
4 6
5 6
样例输出 #3
1
原题
Codeforces——传送门
洛谷——传送门
思路
根据题意,孤立城市即是入度为 0 0 0 的点。
可以证明,对于任意一个由无向边相连的连通图,若存在环,则一定存在一种方案,使得所有无向边变为有向边后,图中不存在任意一点的入度为 0 0 0;否则一定不存在方案。
存在环时,我们可以构建这样一种方案:让构成环的所有无向边变为有向边时方向一致(即同为顺时针或者同为逆时针),这样,无向边变为有向边后环依然存在,同时,连通图内所有点被分为了两类——环中点和其余点,然后再让与环中点相连的未转变为有向边的无向边的指向变为环中点➡其余点,在此过程中连接的其余点转变为环中点,重复此过程直至所有点转变为环中点,最后剩余的无向边可任意指定方向。
而对于不存在环的连通图,产生的孤立城市数量一定可以且最多可以降至 1 1 1 (方案是构建以某一点为根的树)。所以,答案即为不存在环的连通图的个数。
代码
#include <bits/stdc++.h>
using namespace std;
using i64 = long long;
struct DSU
{
std::vector<int> f;
DSU() {}
DSU(int n)
{
init(n);
}
void init(int n)
{
f.resize(n + 1);
std::iota(f.begin() + 1, f.end(), 1);
}
int find(int x)
{
while (x != f[x])
{
x = f[x] = f[f[x]];
}
return x;
}
bool merge(int x, int y)
{
x = find(x);
y = find(y);
if (x == y)
{
return false;
}
f[y] = x;
return true;
}
};
int main()
{
ios::sync_with_stdio(0);
cin.tie(0);
int n, m;
cin >> n >> m;
DSU dsu = DSU(n);
vector<bool> loops(n + 1, 0); // loops[i]为1表示以i为根的并查集有环
int x, y;
while (m--)
{
cin >> x >> y;
bool exist_loop = 0; // 表示x和y合并后的整个并查集是否有环
if (loops[dsu.find(x)] == 1 || loops[dsu.find(y)] == 1) // 如果合并前存在环,则合并后依然有环
exist_loop = 1;
if (dsu.find(x) == dsu.find(y)) // 如果合并前两个点已经在同一个并查集中,那么再加上当前这条边,合并后就能形成环
exist_loop = 1;
dsu.merge(x, y);
if (exist_loop == 1)
loops[dsu.find(x)] = 1; // 如果有环,则在根节点打上标记
}
set<int> st; // set保存各个连通图所在并查集的根节点
for (int i = 1; i <= n; i++)
st.insert(dsu.find(i));
// 答案即为不存在环的连通图的个数
int ans = 0;
for (auto it = st.begin(); it != st.end(); it++)
if (loops[*it] == 0)
ans++;
cout << ans << '\n';
return 0;
}