机试算法讲解: 第39题 DAG之QQ师徒关系

/*
问题:QQ群中师徒关系。判定是否存在有向无环图。
输入:N(多少个结点),M(需要测试的关系) (2<=N,M<=100),接下来是M行,每一行是 x y,表示x是y的师傅,当N=0时,输入终止,数字时0,1,...,N-1
输出:合法师徒为"YES",非法是"NO"
思路:采用队列保存入度为0的节点,每找到一个,删除该节点和以该节点为弧尾的所有节点
*/

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <queue>
#include <vector>
#define MAX 1000
using namespace std;


int main(int argc,char* argv[])
{
	int n,m;
	int i;
	while(EOF!=scanf("%d %d",&n,&m))
	{
		if(0==n && 0==m)
		{
			break;
		}
		vector<int> vecEdge[MAX];//用于建立单链表
		int inDegree[MAX];
		queue<int> queueDegree;//用于存放入度为0的结点
		//初始化入度为0
		for(i = 0 ; i < n ; i++)
		{
			inDegree[i] = 0;
		}
		//获取输入信息
		int x,y;
		for(i = 0 ; i < m ; i++)
		{
			scanf("%d %d",&x,&y);
			//对入度进行加1,同时建立链表关系
			inDegree[y]++;
			vecEdge[x].push_back(y);
		}

		//将入度为0的节点存入队列中
		queue<int> queInDegree;
		for(int i = 0 ; i < n ; i++)
		{
			if(0==inDegree[i])
			{
				queInDegree.push(i);
			}
		}

		//遍历入度为0的节点,开始进行删除操作
		int iCnt = 0;//用于计数是否最终删除了n个节点
		while(!queInDegree.empty())
		{
			int iFront = queInDegree.front();
			//遍历该节点,将所有与之相关的节点的入度减1
			for(i = 0 ; i < vecEdge[iFront].size() ; i++)
			{
				int iRel = vecEdge[iFront][i];
				inDegree[iRel]--;
				//如果减1后的节点的入度为0,则再将该节点放入队列中
				if(0==inDegree[iRel])
				{
					queInDegree.push(iRel);
				}
			}
			//在队列中弹出该节点
			queInDegree.pop();
			//删除该节点对应的单链表
			vecEdge[iFront].clear();
			iCnt++;
		}
		//如果删除了所有的节点,表明是有向无环图
		if(n==iCnt)
		{
			printf("YES\n");
		}
		else
		{
			printf("NO\n");
		}
	}
	system("pause");
	getchar();
	return 0;
}

你可能感兴趣的:(DAG,有向无环图,机试算法)