题目大意:

 

给你一个关系图,判断是否合法。每个人都有师父和徒弟,可以有很多个;

若A是B的师父,B是C的师父,则A也算C的师父。

不合法: 

1) . 互为师徒;(有回路) 
 2) .你的师父是你徒弟的徒弟,或者说你的徒弟是你师父的师父。(出现回路)

思路:

判断有向图中是否存在回路或至少3元环; 
此题至少有三种做法,此处更新拓扑排序的做法:

解题方法:

一:拓扑排序:

1) . 统计每个点的入度;

2) . 将入度为0的点加入队列;

3) . 出去队首元素,将此元素所连接的点入度减一,若此后入度为0则加入队列;

4) . 判断队列循环次数,若等于n则不存在3元环,则此关系图合法;

题目链接:

点击打开链接

#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 = ;
const int M = ;
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=;i<n;++i){
if(in[i]==)Q.push(i);
}
int t=;
while(!Q.empty()){
t++;
int u=Q.front();Q.pop();
for(int i=head[u];i!=-;i=cw[i].nex){
int v=cw[i].v;
in[v]--;
if(in[v]==)Q.push(v);
}
}
if(t==n)flag=;
}
int main(int argc, char const *argv[])
{
int a,b;
while(~scanf("%d%d",&n,&m)&&(n)){
memset(in,,sizeof(in));
tot=-;
memset(head,-,sizeof(head));
for(int i=;i<m;++i){
scanf("%d%d",&a,&b);
add(a,b);
in[b]++;
}
flag=;
tuopu();
if(flag)printf("YES\n");
else printf("NO\n");
}
return ;
}

二: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 = ;
const int M = ;
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]=;
st.push(u);
int v;
for(int i=head[u];i!=-;i=cw[i].nex){
v=cw[i].to;
if(v==fa){
flag=;
break;
}
if(!vis[v]){
dfs(v,u);
if(flag)return;
low[u]=min(low[u],low[v]);
}else if(vis[v]==){
low[u]=min(low[u],dfn[v]);
}
}
if(low[u]==dfn[u]){//缩点
qltNum++;
int t=;
do{
t++;
v=st.top();st.pop();
vis[v]=;
qltMap[v]=qltNum;
if(t>=){
flag=;
return;
}
}while(v!=u);
//cout<<t<<"\n";
}
}
void tarjan(){
for(int i=;i<=n;++i){
if(!vis[i]){
dfs(i,-);
}
if(flag)return;
}
}
void init(){//初始化
while(!st.empty())st.pop();
qltNum=idex=flag=;
tot=-;
memset(head,-,sizeof(head));
memset(vis,,sizeof(vis));
memset(qltMap,,sizeof(qltMap));
}
int main(int argc, char const *argv[]){
int a,b,m;
while(~scanf("%d%d",&n,&m)&&(n)){
init();
memset(head,-,sizeof(head));
for(int i=;i<m;++i){
scanf("%d%d",&a,&b);
a++,b++;
add(a,b);
}
tarjan();
if(flag)printf("NO\n");
else printf("YES\n");
}
return ;
}

HDU3342:判断有向图中是否存在3元环-Tarjan或拓扑排序的更多相关文章

  1. hdu3342-判断有向图中是否存在(至少)3元环或回路-拓扑排序

    一:题目大意:   给你一个关系图,判断是否合法,    每个人都有师父和徒弟,可以有很多个:  不合法:  1) . 互为师徒:(有回路)  2) .你的师父是你徒弟的徒弟,或者说你的徒弟是你师父的 ...

  2. <数据结构>XDOJ323.判断有向图中是否有环

    问题与解答 问题描述 判断有向图中是否有环. 输入格式 输入数据第一行是一个正整数,表示n个有向图,其余数据分成n组,每组第一个为一个整数,表示图中的顶点个数n,顶点数不超过100,之后为有向图的邻接 ...

  3. hdoj 4324 Triangle LOVE【拓扑排序判断是否存在环】

    Triangle LOVE Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Tot ...

  4. 有向图和拓扑排序Java实现

    package practice; import java.util.ArrayDeque; import java.util.Iterator; import java.util.Stack; pu ...

  5. Lua中的元表与元方法

    [前言] 元表对应的英文是metatable,元方法是metamethod.我们都知道,在C++中,两个类是无法直接相加的,但是,如果你重载了“+”符号,就可以进行类的加法运算.在Lua中也有这个道理 ...

  6. Expm 10_1 带负权值边的有向图中的最短路径问题

    [问题描述] 对于一个带负权值边的有向图,实现Bellman-Ford算法,求出从指定顶点s到其余顶点的最短路径,并判断图中是否存在负环. package org.xiu68.exp.exp10; p ...

  7. DFS应用——遍历有向图+判断有向图是否有圈

    [0]README 0.1) 本文总结于 数据结构与算法分析, 源代码均为原创, 旨在 理解 "DFS应用--遍历有向图+判断有向图是否有圈" 的idea 并用源代码加以实现 : ...

  8. HDU3342有向图判圈DFS&&拓扑排序法

    HDU3342 Legal or Not 题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3342 题目意思:一群大牛互相问问题,大牛有不会的,会被更厉害 ...

  9. POJ——1308Is It A Tree?(模拟拓扑排序判断有向图是否为树)

    Is It A Tree? Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 28399   Accepted: 9684 De ...

随机推荐

  1. 【SVN】提交报错:×××文件is not under version control

    解决方法:1.删除出错的文件,然后在出错文件所在文件夹执行还原操作 2.VS中可将文件先排除在项目外,再包含在项目内,即可正常提交

  2. 记录解决java.io.IOException: Server returned HTTP response code: 500 for URL:xxxxxxxx

    踩坑经历 因为项目需要去对接别的接口,使用URLConnection POST请求https接口,发送json数组时遇到java.io.IOException: Server returned HTT ...

  3. 3.1 开始使用 redux

    前面我们介绍了 flux 架构以及其开源实现 redux,在这一节中,我们将完整的介绍 redux: redux 介绍 redux 是什么 redux 概念 redux 三原则 redux Store ...

  4. error C1010: 在查找预编译头时遇到意外的文件结尾。是否忘记了向源中添加“#include "stdafx.h"”?

    解决方案: 属性>预编译头>不使用预编译头>应用

  5. Java类与类的关系、继承与多态、重写与重载

    Java类与类的关系 (1)is-a包括了 继承,实现关系 (2)has-a包括了 关联,聚合,组合关系 (3)use-a包括了 依赖关系 实现关系: 实现指的是一个class类实现interface ...

  6. JAVA集合--Iterator接口

        本文首发于cartoon的博客     转载请注明出处:https://cartoonyu.github.io/cartoon-blog     上一篇文章中我在集合元素的遍历中已经有涉及到I ...

  7. null == null 或者 [] == [] 或者{} == {} 或者alert(1|| 2) 或者alert(1&& 2) 结果及原理

    相信面试的小伙伴们都会遇到此头大的问题,是不是很想骂一句面试官:你白痴啊,鬼都用不着的东西拿来问,你还别说,这些看似用不着的东西却包含着最基础的原理,那我们来理一理. 1.alert(1||2)和 a ...

  8. 如果通过cookies和localStorage取值?

    1. getCook : 设定setCookie值 let setCookie = setCookie('wan',data,7); function setCookie(c_name,value,e ...

  9. 装箱与拆箱(TDB)

    装箱:把值类型转换为引用类型 拆箱:把引用类型转换为值类型 只能对之前装箱的变量进行拆箱.需要强制转换.

  10. ArrayList、Vector、LinkedList的区别

    ArrayList.Vector.LinkedList的区别 1.底层数据结构: ArrayList底层实现是动态数组 Vector底层实现是动态数组 LinkedList底层实现是双链表  2.扩容 ...