图结构练习——判断给定图是否存在合法拓扑序列

Time Limit: 1000ms   Memory limit: 65536K  有疑问?点这里^_^

题目描述

 给定一个有向图,判断该有向图是否存在一个合法的拓扑序列。

输入

 输入包含多组,每组格式如下。

第一行包含两个整数n,m,分别代表该有向图的顶点数和边数。(n<=10)
后面m行每行两个整数a b,表示从a到b有一条有向边。
 

输出

 若给定有向图存在合法拓扑序列,则输出YES;否则输出NO。

 

示例输入

1 0
2 2
1 2
2 1

示例输出

YES
NO 网上看到有人的思路很巧妙,忍不住就稍作修改,贴了上来:http://www.cnblogs.com/luyingfeng/archive/2013/07/29/3223090.html第一种思路是直接判断环是否存在的思路,这种思路采用dfs算法,是非常规思路:
 #include<stdio.h>
#include<string.h>
#include<stdlib.h>
int vis[];
int m,n,u,v;
int map[][];
int dfs(int u)//深度优先搜索遍历
{
vis[u]=-;//标记-1,正在访问
for(v=; v<=m; v++)
{
if(map[u][v])//如果v是u的后继元素
{
if(vis[v]<)//如果v元素是正在访问中的状态
return ;//存在自环
//如果存在的不是自环
if(!vis[v]&&!dfs(v))//v元素还没有被访问而且v的后继元素和前面的正在访问的元素构成了回路
return ;
}
}
//若果u的后继结点全部没有形成自回路或者是回路
vis[u]=;//标记1,访问完了,删除此节点
return ;
}
int toposort()
{
for(u=; u<=m; u++)
{
if(!vis[u])//如果u节点还没有访问
{
if(!dfs(u))//如果dfs的返回值是0,强制退出排序函数toposort,表明存在环
return ;
}
}
return ;//如果u从1到m全部遍历完
}
int main()
{
while(~scanf("%d %d",&m,&n)&&(m+n!=))
{
memset(vis,,sizeof(vis));
memset(map,,sizeof(map));
for(int i=; i<=n-; i++)
{
scanf("%d %d",&u,&v);
map[u][v]=;
}
if(toposort())//如果返回值是1,不存在回路,无论是自回路或者是回路
printf("YES\n");
else printf("NO\n");//如果返回值是0
}
return ;
}
常规思路,也是书上的思路,即判断是否存在入度为0的节点,若在循环未结束的时候,就找不到入度为0的节点,则必存在环
 #include<stdio.h>
#include<stdlib.h>
#include<string.h>
int map[][],count[];
int flag;
int u,v,vis;
int main()
{
int m,n;
while(~scanf("%d %d",&m,&n)&&(n!=||m!=))
{
memset(map,,sizeof(map));
memset(count,,sizeof(count));//每个节点的入度初始为0;
vis=;//标记变量,用于帮助最后输出
for(int i=; i<=n-; i++)
{
scanf("%d %d",&u,&v);
map[u][v]=;
count[v]++;
}
for(int i=; i<=m-; i++)
{
int flag=;
for(u=; u<=m; u++)
{
if(count[u]==)
{
flag=;//只要有入度为0的点就变为1
count[u]--;//删除掉这个节点
for(v=; v<=m; v++)//凡是与该节点有关的所有结点入度去掉1;
{
if(map[u][v])
{
count[v]--;
}
}
break;
}
}
if(flag==)//如果没有入度为0的点,就代表没有拓扑序列
{
vis=;
break;
}
}
if(vis==)
printf("YES\n");
else printf("NO\n");
}
return ;
}

以上两种算法全部采用邻接矩阵的方法,但是采用邻接表的方法更具有一般性,这也是以上两种方法的不足之处。

以下是用邻接表的方法:

 #include<stdio.h>
#include<string.h>
#include<stdlib.h>
struct vode
{
int v;
struct vode *next;
};
struct vode *f[];
int count[];
int stack[],top=;
int m,n;
int topsort()
{
int i,sum=;
int flag;
while()
{
flag=;
for(i=;i<=m;i++)
{
if(count[i]==)
{
stack[top++]=i;
sum++;
count[i]--;//删除i节点
struct vode *p;
for(p=f[i];p!=NULL;p=p->next)//把i节点的邻接点的入度都减1
{
int t=p->v;
count[t]--;
}
flag=;
}
if(flag==)break;//如果找到了入度是0的节点,从头开始再找入度是0的节点
}
if(flag==)//循环完了之后再也找不到入度是0的节点,这时候可能会有环,也可能没有环
{
break;
}
}
return sum;
}
int main()
{
while(scanf("%d%d",&m,&n)!=EOF)
{
int i;
memset(count,,sizeof(count));
for(i=;i<=m;i++)
f[i]=NULL;
for(i=;i<=n;i++)
{
int u,v;
scanf("%d%d",&u,&v);
count[v]++;
struct vode *p;
p=(struct vode *)malloc(sizeof(struct vode));
p->v=v;
p->next=f[u];
f[u]=p;
} int sum=topsort();
if(sum!=m)printf("NO\n");
else printf("YES\n");
/*
通过这个循环可以得到最终每个节点的入度,如果是合法的拓扑序列,最终的结果应当都是-1
for(i=1;i<=m;i++)
printf("%d ",count[i]);
printf("\n");
通过下面这个循环可以得到最终一个拓扑序列(如果合法),这个序列可能只是合法序列当中的一个
for(i=1;i<=m;i++)
printf("%d ",stack[i]);
printf("\n");
*/
}
return ;
}

简化后的代码:

 #include<stdio.h>
#include<string.h>
#include<stdlib.h>
struct vode
{
int v;
struct vode *next;
};
struct vode *f[];
int m,n;
int rudu[];
int stack[],top;
void hs()
{
int i,k=;
while(k=!k)
for(i=;i<=m;i++)
if(rudu[i]==)
{
k=;
rudu[i]--;
stack[top++]=i;
struct vode *p;
for(p=f[i];p!=NULL;p=p->next)
rudu[p->v]--;
break;
}
}
int main()
{
while(scanf("%d%d",&m,&n)!=EOF)
{
memset(f,,sizeof(f));
memset(rudu,,sizeof(rudu));
memset(stack,,sizeof(stack));
top=;
int i;
for(i=;i<=n;i++)
{
int u,v;
scanf("%d%d",&u,&v);
rudu[v]++;
struct vode *p;
p=(struct vode *)malloc(sizeof(struct vode));
p->v=v;
p->next=f[u];
f[u]=p;
}
hs();
/*//下面的循环可以显示出拓扑序列
for(i=0;i<=top-1;i++)
printf("%d ",stack[i]);
printf("\n");
*/
if(top==m)printf("YES\n");
else printf("NO\n");
}
return ;
}

测试数据:

5 4

1 3

2 3

3 4

3 5

输出:

YES

-1 -1 -1 -1 -1

1 2 3 4 5

测试连接:http://wenku.baidu.com/view/bb32ee2e4b73f242336c5f53.html

图结构练习——判断给定图是否存在合法拓扑序列(dfs算法(第一个代码),邻接矩阵(前两个代码),邻接表(第三个代码))的更多相关文章

  1. SDUT2140图结构练习——判断给定图是否存在合法拓扑序列

    拓扑序列的判断方法为不存在有向环,代码实现的话有两种,一种是直接去判断是否存在环,较为难理解一些,另一种的话去判断结点入度,如果存在的入度为0的点大于一个,则该有向图肯定不存在一个确定的拓扑序列 #i ...

  2. 图结构练习——判断给定图是否存在合法拓扑序列(sdutoj)

    #include<stdio.h>#include<string.h>int d[15],map[15][15],vis[15];int main(){    int i,j, ...

  3. SDUT OJ 数据结构实验之图论十:判断给定图是否存在合法拓扑序列

    数据结构实验之图论十:判断给定图是否存在合法拓扑序列 Time Limit: 1000 ms Memory Limit: 65536 KiB Submit Statistic Discuss Prob ...

  4. SDUT-2140_判断给定图是否存在合法拓扑序列

    数据结构实验之图论十:判断给定图是否存在合法拓扑序列 Time Limit: 1000 ms Memory Limit: 65536 KiB Problem Description 给定一个有向图,判 ...

  5. 设计一个算法,採用BFS方式输出图G中从顶点u到v的最短路径(不带权的无向连通图G採用邻接表存储)

    思想:图G是不带权的无向连通图.一条边的长度计为1,因此,求带顶点u和顶点v的最短的路径即求顶点u和顶点v的边数最少的顶点序列.利用广度优先遍历算法,从u出发进行广度遍历,类似于从顶点u出发一层一层地 ...

  6. 拓扑排序 判断给定图是否存在合法拓扑序列 自家oj1393

    //拓扑排序判断是否有环 #include<cstdio> #include<algorithm> #include<string.h> #include<m ...

  7. 数据结构实验之图论十:判断给定图是否存在合法拓扑序列(SDUT 2140)

    分析:BFS判断是否有环. #include<bits/stdc++.h> using namespace std; typedef long long ll; int gra[200][ ...

  8. Theano学习笔记(三)——图结构

    图结构(Graph Structures)这是理解Theano该基金会的内部运作. Theano编程的核心是用符号占位符把数学关系表示出来. 图结构的组成部分 如图实现了这段代码: importthe ...

  9. 第6章 图的学习总结(邻接矩阵&邻接表)

    我觉得图这一章的学习内容更有难度,其实图可以说是树结构更为普通的表现形式,它的每个元素都可以与多个元素之间相关联,所以结构比树更复杂,然而越复杂的数据结构在现实中用途就越大了,功能与用途密切联系,所以 ...

随机推荐

  1. TP中手动加载类库

    加载第三方类库,包括不符合命名规范和后缀的类库,以及没有使用 命名空间或者空间和路径不一致的类库.可手动加载. // 导入Org类库包 Library/Org/Util/Date.class.php类 ...

  2. (转载)XML解析之-XStream解析

    转载来源:http://hwy584624785.iteye.com/blog/1168680 本例使用XStream生成一个xml文件,再发序列化xml文件内容. XStream是一个简单的类库,可 ...

  3. [mysql] Some non-transactional changed tables couldn't be rolled back

    使用peewee的事务时,碰到一个郁闷的问题,事务似乎无效! 于是简化了下模型,写了简单的测试代码,发现问题,如题所示. 找到解答: https://github.com/etianen/django ...

  4. 如何解决phpcms后台验证码不显示的问题

    方法一: 主要在于是否开启gd库 查看办法 找到php.ini文件 搜索extension=php_gd2.dll这段代码(windows) 然后把前面的;符号去掉即可. centOS6.5中可能需要 ...

  5. c语言——知识点

    环境: ubuntu 13.04 32位 gcc version 4.7.3 ++i,i++ 代码如下: #include <stdio.h> main() { int i; //test ...

  6. Contains Duplicate III

    Given an array of integers, find out whether there are two distinct indices i and j in the array suc ...

  7. IPC----哲学家就餐问题(并发与互斥)

    哲学家就餐问题描述: 5个哲学家,5个筷子.5个哲学家围坐在一张桌子上,筷子放在分别放在每个哲学家的两旁.如果所有哲学家在某个时刻同时拿起左边的筷子,那么右边的筷子就都被其他的哲学家拿了,造成大家都无 ...

  8. 【leetcode】Unique Binary Search Trees II

    Unique Binary Search Trees II Given n, generate all structurally unique BST's (binary search trees) ...

  9. winserver2008 Oracle 11g 安装

    .在Windows Server2008R2上安装Oracle Database 11g Release 2,下载64位的安装程序,地址: 文件1:http://download.oracle.com ...

  10. assign() 方法

    assign() 方法可加载一个新的文档. 语法 location.assign(URL) <html> <head> <script type="text/j ...