当前位置:   article > 正文

HDU3342 判断有向图中是否存在三元环 拓扑排序 tarjan_判断一般图有没有三元环

判断一般图有没有三元环

题目大意:

给你一个关系图,判断是否合法,
   每个人都有师父和徒弟,可以有很多个;
   且 若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序与遍历图的顺序无关,是不变的。
一个无向完全图给部分边定向后若不存在环,则总有一种给其他边定向的方式使得这个有向图无环
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

有向图判断环的方法:

DFS标记白灰黑
拓扑排序
Tarjan

无向图判断环的方法:

改动的拓扑排序(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;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65

法二:tarjan

#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;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/羊村懒王/article/detail/64601
推荐阅读
相关标签
  

闽ICP备14008679号