为什么打算重新写一下呢,因为最近一直在做并查集的题.emmm/
现在讲两种dfs判断环的方式.
对于无向图只需对另一一个点做一次dfs即可,因为任意一个点一定可以都到的.
int vis[N]; void dfs(int u,int fa)//判断有没有环. { if(vis[u]) {flag=1;return;} vis[u]=1; for(int i=0;i<v[u].size();i++) { if(v[u][i]==fa) continue; dfs(v[u][i],u); } }//对于单个联通的无向图直接dfs一次即可.
对于有向图呢?
有向图做法和无向图做法大同小异.你的vis数组存3个状态即可,因为不确定树根是否能遍历到环,我们用3个vis状态可以写...
用vis[i]=1,表示前面的点可以遍历到这个点且没产生环,那么,显然的一个结论,我下次遍历这个点是毫无意义的,vis[i]=0,表示我正在遍历的点,假如我正在遍历的点下次还遍历到了,那么肯定这就有环了,否则就遍历儿子,最后把vis[i]=1,然后枚举其他节点为根,复杂度是O(N)的.
#include <bits/stdc++.h> using namespace std; const int N=2e4+5; vector<int>v[N]; int vis[N]; bool dfs(int u) { vis[u]=0; for(int i=0;i<v[u].size();i++) { if(vis[v[u][i]]==0) return true; if(vis[v[u][i]]==-1&&dfs(v[u][i])) return true; } vis[u]=1; return false; } int main() { int n,m;//n个点m条边. cin>>n>>m; memset(vis,-1,sizeof vis); for(int i=1;i<=m;i++) { int x,y; scanf("%d%d",&x,&y); v[x].push_back(y); }int flag=0; for(int i=1;i<=n;i++) { if(vis[i]==-1) { if(dfs(i)) flag=1; } } flag==1?puts("yes"):puts("no"); return 0; }
我们再来看这个题目,给定大小关系要你判断有没有矛盾...2333
对于=我们可以建一个并查集,直接用祖先代表它的关系,对于>我们可以把大的和小的建一条有向边,除此之外,这个题就变成了给你一幅有图,要你判断图中是否有环因为方向不能错哈.代码就很简单了2333
#include <bits/stdc++.h> using namespace std; const int N=2e5+5; int fa[N],id,vis[N]; struct vv{ int from,to; }a[N]; int f(int x) { if(x==fa[x]) return x; else return fa[x]=f(fa[x]); } void init() { for(int i=0;i<=N-5;i++) fa[i]=i; memset(vis,-1,sizeof vis); } vector<int>v[N]; bool dfs(int u) { vis[u]=0; for(int i=0;i<v[u].size();i++) { if(vis[v[u][i]]==0) return true; if(vis[v[u][i]]==-1&&dfs(v[u][i])) return true; } vis[u]=1; return false; } int main() { int n,m; scanf("%d%d",&n,&m); init(); for(int i=1;i<=m;i++) { int x,y;char c; cin>>x>>c>>y; if(c=='=') { if(f(x)!=f(y)) { fa[f(x)]=f(y); } } else if(c=='>') { a[++id]={x,y}; } else { a[++id]={y,x}; } } for(int i=1;i<=id;i++) { v[f(a[i].from)].push_back(f(a[i].to)); } int flag=0; for(int i=0;i<n;i++) { if(vis[i]==-1) { if(dfs(i)) flag=1; } } if(flag) puts("inconsistent"); else puts("consistent"); return 0; }
坑点在点是5e4,边大于5e4,数组开5e4报wa,导致debug很久...emmm/