7-6 判断DFS序列的合法性 (20分)

给出一个有向图,请判断给出的深度优先遍历序列是否合法。 例如对于如下的图
在这里插入图片描述
0 1 4 2 5 3 和 0 2 5 1 4 3 和 3 2 5 1 4 0 都是合法的DFS序列,但0 2 3 1 4 5则不是合法的DFS序列。

输入格式:
第一行给出顶点数 M 和边数 N,以空格分隔;顶点标号从 0 到 M−1。其中 M 不超过 100。 之后 N 行,每行按如下格式给出图中的各条边:

ID1 ID2

这表示从编号为ID1的顶点到编号为ID2的顶点的有向边。 之后一行给出整数 K,表示有 K 个序列待检验的序列。 接下来的 K 行,每行给出 M 个以空格分隔的整数表示DFS序列。

输出格式:
对于每一个待检验序列,输出 Yes 表示合法,No 表示不合法。

输入样例:

6 9
0 1
0 2
0 3
2 1
3 2
4 2
1 4
2 5
4 5
3
0 1 4 2 5 3
0 2 5 1 4 3
0 2 3 1 4 5

输出样例:

Yes
Yes
No

思路:

判断DFS序列是否合法,那就模拟DFS,一旦遇到仍有邻接边未被访问,但是序列下一个点并不是邻接点,则说明是不合法序列。
代码有些地方略显冗长,不过问题不大,见谅!

源码:

#include<stdio.h>
#include<stdlib.h>
#define MaxNum 101
typedef struct GraphNode * MyGraph;
struct GraphNode{
	int Nv;
	int Ne;
	int Graph[MaxNum][MaxNum];
};
MyGraph create(int M,int N)
{
	MyGraph G=(MyGraph)malloc(sizeof(struct GraphNode));
	G->Nv=M;
	G->Ne=N;
	int i,j;
	for(i=0;i<MaxNum;i++)
	{
		for(j=0;j<MaxNum;j++)
		{
			G->Graph[i][j]=0; 
		}
	}
	
	return G;
}
void Insert(MyGraph G,int v1,int v2)
{
	G->Graph[v1][v2]=1;
}
int DFS(MyGraph G,const int *refer,int *Visited,int i)
{
	int value=refer[i];
	Visited[value]=1;
	int j;int f;
	int flag=1;
	for(j=i+1;j<G->Nv;j++)	
	{
		if(!Visited[refer[j]])
		{ 
			if(G->Graph[value][refer[j]])
			{
				flag=DFS(G,refer,Visited,j);
			}
			else
			{
				/*要判断是否refer[i]已经是孤立点
				若不是孤立点,但是refer[i]和refer*[i]并不连通,说明错误*/
				int t;
				for(t=0;t<G->Nv;t++)
				{
					if(G->Graph[refer[i]][t]&&!Visited[t])flag=0;
				}
			}
			
			if(!flag)break;
		}	
	} 
	
	return flag;
}
int IsValid(MyGraph G,const int *refer,int *Visited)
{
	int i;
	int f=1;
	for(i=0;i<G->Nv;i++)
	{
		if(!Visited[refer[i]])
		{
			f=DFS(G,refer,Visited,i);
		}
		if(f)continue;
		else return 0;
	}
	
	return 1;
}
void JudgeDFS(MyGraph G,const int *refer)
{
	int Visited[G->Nv]={0};
	int flag;
	flag=IsValid(G,refer,Visited);
	if(flag)
		printf("Yes\n");
	else
		printf("No\n");
}
int main()
{
	int N,M;
	scanf("%d%d",&M,&N);
	MyGraph G=create(M,N); 
	int i;
	int v1,v2;
	for(i=0;i<N;i++)	
	{
		scanf("%d%d",&v1,&v2);
		Insert(G,v1,v2);
	}
	int n,j;
	scanf("%d",&n);
	int refer[G->Nv];
	for(i=0;i<n;i++)
	{
		for(j=0;j<G->Nv;j++)
		{
			scanf("%d",&refer[j]);
		}
		JudgeDFS(G,refer);
	}
	
	return 0;
} 
  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值