赞
踩
给你一个关系图,判断是否合法,
每个人都有师父和徒弟,可以有很多个;
且 若A是B的师父,B是C的师父,则A是C的师父。
不合法的情况:
1) 互为师徒;
2) 你的师父是你徒弟的徒弟,或者说你的徒弟是你师父的师父。(3元环或多元环)
题目链接:点击做题
判断有向图中是否存在至少3元环;
也就是判断有没有回路自环啥的东西;
此题至少有三种做法。
有向图,无向图判断环的方法及判断负环的方法:
有向图判断环的方法:
1. DFS标记白灰黑
2. 拓扑排序
3. Tarjan
无向图判断环的方法:
1. 改动的拓扑排序(BFS:du[i]<=1,push)
2. DFS标记白灰黑
3. 并查集
拓扑序和rdfs序与遍历图的顺序无关,是不变的。
一个无向完全图给部分边定向后若不存在环,则总有一种给其他边定向的方式使得这个有向图无环
有向图判断环的方法:
无向图判断环的方法:
改动的拓扑排序(BFS:du[i]<=1,push)
DFS标记白灰黑
并查集
1) . 统计每个点的入度;
2) . 将入度为0的点加入队列;
3) . 出去队首元素,将此元素所连接的点入度减一,若此后入度为0则加入队列;
4.) 判断队列循环次数,若等于n则不存在回路,则此关系图合法;
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<cmath> #include<cstdlib> #include<queue> #include<map> #include<stack> #include<vector> #include<ctime> using namespace std; const int N = 2005; const int M = 3000005; int n,m; int tot,flag; int in[N],head[N]; struct lp { int u,v,nex; lp(){} lp(int a,int b,int c): u(a),v(b),nex(c){} }cw[N]; void add(int a,int b){ cw[++tot]=lp(a,b,head[a]); head[a]=tot; } void tuopu(){ queue<int>Q; while(!Q.empty())Q.pop(); for(int i=0;i<n;++i){ if(in[i]==0)Q.push(i); } int t=0; while(!Q.empty()){ t++; int u=Q.front();Q.pop(); for(int i=head[u];i!=-1;i=cw[i].nex){ int v=cw[i].v; in[v]--; if(in[v]==0)Q.push(v); } } if(t==n)flag=1; } int main(int argc, char const *argv[]) { int a,b; while(~scanf("%d%d",&n,&m)&&(n)){ memset(in,0,sizeof(in)); tot=-1; memset(head,-1,sizeof(head)); for(int i=0;i<m;++i){ scanf("%d%d",&a,&b); add(a,b); in[b]++; } flag=0; tuopu(); if(flag)printf("YES\n"); else printf("NO\n"); } return 0; }
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<cmath> #include<cstdlib> #include<queue> #include<map> #include<stack> #include<vector> #include<ctime> using namespace std; const int N = 105; const int M = 3000005; int n,tot,flag,idex; int head[N],vis[N]; int low[N],dfn[N]; int qltNum; int qltMap[N]; stack<int>st; struct lp { int to,nex; lp(){} lp(int a,int b): to(a),nex(b){} }cw[N*N]; void add(int a,int b){ cw[++tot]=lp(b,head[a]); head[a]=tot; } void dfs(int u,int fa){ dfn[u]=low[u]=++idex; vis[u]=1; st.push(u); int v; for(int i=head[u];i!=-1;i=cw[i].nex){ v=cw[i].to; if(v==fa){ flag=1; break; } if(!vis[v]){ dfs(v,u); if(flag)return; low[u]=min(low[u],low[v]); //if(low[v] > dfn[u]) bridge }else if(vis[v]==1){ low[u]=min(low[u],dfn[v]); } } if(low[u]==dfn[u]){ qltNum++; int t=0; do{ t++; v=st.top();st.pop(); vis[v]=2; qltMap[v]=qltNum; if(t>=3){ flag=1; return; } }while(v!=u); //cout<<t<<"\n"; } } void tarjan(){ for(int i=1;i<=n;++i){ if(!vis[i]){ dfs(i,-1); } if(flag)return; } } void init(){ while(!st.empty())st.pop(); qltNum=idex=flag=0; tot=-1; memset(head,-1,sizeof(head)); memset(vis,0,sizeof(vis)); memset(qltMap,0,sizeof(qltMap)); } #define DEBUG int main(int argc, char const *argv[]) { int a,b,m; #ifdef DEBUG freopen("D:in.in", "r", stdin); freopen("D:out.out", "w", stdout); #endif while(~scanf("%d%d",&n,&m)&&(n)){ init(); memset(head,-1,sizeof(head)); for(int i=0;i<m;++i){ scanf("%d%d",&a,&b); a++,b++; add(a,b); } tarjan(); if(flag)printf("NO\n"); else printf("YES\n"); } return 0; }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。