图结构练习——判断给定图是否存在合法拓扑序列(dfs算法(第一个代码),邻接矩阵(前两个代码),邻接表(第三个代码))
图结构练习——判断给定图是否存在合法拓扑序列
Time Limit: 1000ms Memory limit: 65536K 有疑问?点这里^_^
题目描述
输入
输出
示例输入
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算法(第一个代码),邻接矩阵(前两个代码),邻接表(第三个代码))的更多相关文章
- SDUT2140图结构练习——判断给定图是否存在合法拓扑序列
拓扑序列的判断方法为不存在有向环,代码实现的话有两种,一种是直接去判断是否存在环,较为难理解一些,另一种的话去判断结点入度,如果存在的入度为0的点大于一个,则该有向图肯定不存在一个确定的拓扑序列 #i ...
- 图结构练习——判断给定图是否存在合法拓扑序列(sdutoj)
#include<stdio.h>#include<string.h>int d[15],map[15][15],vis[15];int main(){ int i,j, ...
- SDUT OJ 数据结构实验之图论十:判断给定图是否存在合法拓扑序列
数据结构实验之图论十:判断给定图是否存在合法拓扑序列 Time Limit: 1000 ms Memory Limit: 65536 KiB Submit Statistic Discuss Prob ...
- SDUT-2140_判断给定图是否存在合法拓扑序列
数据结构实验之图论十:判断给定图是否存在合法拓扑序列 Time Limit: 1000 ms Memory Limit: 65536 KiB Problem Description 给定一个有向图,判 ...
- 设计一个算法,採用BFS方式输出图G中从顶点u到v的最短路径(不带权的无向连通图G採用邻接表存储)
思想:图G是不带权的无向连通图.一条边的长度计为1,因此,求带顶点u和顶点v的最短的路径即求顶点u和顶点v的边数最少的顶点序列.利用广度优先遍历算法,从u出发进行广度遍历,类似于从顶点u出发一层一层地 ...
- 拓扑排序 判断给定图是否存在合法拓扑序列 自家oj1393
//拓扑排序判断是否有环 #include<cstdio> #include<algorithm> #include<string.h> #include<m ...
- 数据结构实验之图论十:判断给定图是否存在合法拓扑序列(SDUT 2140)
分析:BFS判断是否有环. #include<bits/stdc++.h> using namespace std; typedef long long ll; int gra[200][ ...
- Theano学习笔记(三)——图结构
图结构(Graph Structures)这是理解Theano该基金会的内部运作. Theano编程的核心是用符号占位符把数学关系表示出来. 图结构的组成部分 如图实现了这段代码: importthe ...
- 第6章 图的学习总结(邻接矩阵&邻接表)
我觉得图这一章的学习内容更有难度,其实图可以说是树结构更为普通的表现形式,它的每个元素都可以与多个元素之间相关联,所以结构比树更复杂,然而越复杂的数据结构在现实中用途就越大了,功能与用途密切联系,所以 ...
随机推荐
- zabbix之MySQL数据库的安装
转载自:http://www.ttlsa.com/mysql/install-mysql5_6/ 启动MySQL并制定套接字 mysql -u user -ppassword -S 指定socket路 ...
- 细化如何安装LNMP + Zabbix 监控安装文档以及故障排除
1.LNMP所需安装包: 上传如下软件包到/soft目录中 mysql- (centos6. 64位自带)也可根据版本自行挑选,前提你了解这个版本 pcre-8.36.tar.gz nginx-.ta ...
- JAVA 回调机制(callback)
序言 最近学习java,接触到了回调机制(CallBack).初识时感觉比较混乱,而且在网上搜索到的相关的讲解,要么一言带过,要么说的比较单纯的像是给CallBack做了一个定义.当然了,我在理解了回 ...
- STL---总结
文章转自:http://www.cnblogs.com/biyeymyhjob/archive/2012/07/22/2603525.html 一.STL的六大组件 容器(Container),是一种 ...
- POJ 1190(深搜)
http://poj.org/problem?id=1190 又有好久没做搜索的题了,没想到做一个卡了我那么久,想哭啊. 一个中文题,思路呢也就是搜索呗,一层一层往上面搜,不过这里有两个比较重要的地方 ...
- cannot use the same dataset for report.dataset and page.dataset
把page中的dataset中填的数据表删除.(改成not assigned)
- 5.SpringMVC静态文件的访问
我们在进行springMVC开发时,必定会在jsp页面引入js文件.img文件和css文件.大多数人会将这些分类存放在WebRoot文件下新建的文件夹下面.同时,会在web.xml文件中配置拦截所有请 ...
- vmstat uptime 系统状态脚本
#!/bin/bash # # Command :vmstat,uptime #Capture_Stats - Gather System Performance Statistics ####### ...
- Mathematics:Find a multiple(POJ 2356)
找组合 题目大意:给你N个自然数,请你求出若干个数的组合的和为N的整数倍的数 经典鸽巢原理题目,鸽巢原理的意思是,有N个物品,放在N-1个集合中,则一定存在一个集合有2个元素或以上. 这一题是说有找出 ...
- ios电话/密码/验证码/身份证的正则表达式
// 一 .电话号码正则表达式 -(BOOL)testPhoneNumber:(NSString *)text { NSString *regex =@"(13[0-9]|0[1-9]|0[ ...