我们可以使用并查集来判断一个图中是否存在环:
对于无向图来说,在遍历边 ( u − > v ) (u->v) (u−>v) 时,如果结点 u u u 和结点 v v v 的“父亲”相同,那么结点 u u u 和结点 v v v 在同一个环中。
判断无向图是否有环,只需要在合并时加判断即可
每出现一次连接两个已经连通的顶点,图中就会多一个环
而DFS判无向图中连通块环的个数,可以通过点数和边数的个数来判断
设点数 V V V,边数 E E E,如果 V = E + 1 V=E+1 V=E+1,那么就无环, V = E V=E V=E 就是一个环,依次…
1.判断每个连通块环的个数是否为一个
(每个连通块满足顶点和边数相等
2.小希的迷宫
题意:
判断所给图是否连通且无环,满足输出 “Yes”,否则输出 “No”
思路:
并查集判断连通并且无环即可
code:
#include
#define endl '\n'
#define ll long long
#define ull unsigned long long
#define ld long double
#define all(x) x.begin(), x.end()
#define eps 1e-6
using namespace std;
const int maxn = 1e5 + 9;
const int mod = 998244353;
ll n, m;
int f[maxn];
int x, y;
bool flag = 0;
int find(int x)
{
int r = x, j, k = x;
while(r != f[r]) r = f[r]; // 寻找根节点
while(k != r)
{
j = f[k]; // 暂存此时k的父节点
f[k] = r; // 将k的父节点改为根节点
k = j; // k移到父节点 直至全改为根节点
}
return r;
}
void merge(int fx, int fy){
fx = find(fx); fy = find(fy);
if(fx != fy) f[fx] = fy;
else flag = 1;// 连接了两个已经连通的顶点,说明会形成环
}
unordered_map<int,int> ma;
void work()
{
if(x == 0 && y == 0){// 空图输出Yes
cout << "Yes\n";return;
}
for(int i = 1; i <= 1e5; ++i) f[i] = i;
ma[x] = ma[y] = 1;
merge(x, y);
while(cin >> x >> y && x != 0){
ma[x] = ma[y] = 1;
merge(x, y);
}
set<int> se;// 所有出现的顶点的父节点塞进set
for(int i = 1; i <= 1e5; ++i) if(ma[i])
{
int p = find(i);
se.insert(p);
}
if(!flag && se.size() == 1) cout << "Yes\n";
else cout << "No\n";
ma.clear();
flag = 0;
}
int main()
{
ios::sync_with_stdio(0);
while(cin >> x >> y && x != -1)
work();
return 0;
}