【题目要求】
现在你总共有 N 门课需要选择,记为 0 到 N-1。
在选修某些课程之前需要一些先修课程。 例如,想要学习课程 0 ,你需要先完成课程 1 ,我们用一个匹配来表示他们,如: 0,1
给定课程总量,条件条数以及它们的先决条件,判断是否可能完成所有课程的学习?并两门课程的教学安排顺序是否正确?
【输入形式】
第一行,输入:课程数N,课程之间的关系数M
第二行开始,输入M行,输入课程关系(若要学习课程1,需要先完成课程2)输入:课程1,课程2
继续输入两个课程编号c1,c2.
【输出形式】
第一行输出:是否可以完成课程(true/false)
第二行输出:是否允许先安排学习课程c1在安排学习c2(true/false),如果第一行为false,则不输出第二行。
【样例输入1】
4 4
1,0
2,0
3,1
3,2
3,0
【样例输出1】
true
true
【样例说明1】
总共有 4 门课程。要学习课程 0,你应该先完成课程 1 和课程 2。并且课程 1 和课程 2 都应该排在课程 3之后。这是可能的,因此第一行输出true。
教学计划允许先安排学习课程3,再安排学习课程0,因此第二行输出true。
【样例输入2】
2 2
1,0
0,1
1,0
【样例输出2】
false
【样例说明2】
总共有 2 门课程。学习课程0之前,你还应先完成课程1;并且学习课程1之前,你需要先完成课程0。这是不可能的,因此第一行输出false。第二行不输出。
【代码】
#include<iostream>
#include<stack>
#include<cstring>
#define MAX 100
using namespace std;
typedef struct ArcNode //边结点
{int adjvex; //顶点下标ArcNode* next;
} ArcNode;
typedef struct
{int in; //in是入度int vertex; //顶点信息ArcNode* firstEdge;
} vertexNode, VertexNode[MAX];class ALGraph
{
private:int vertexNum, arcNum; //顶点数,边数VertexNode adjList; //顶点数组stack<vertexNode> s; //栈int count = 0; //计数int result[MAX]; //存储拓扑排序结果的数组
public:ALGraph(int v[], int n, int e);bool TopologicalSort(); //拓扑排序bool isReasonable(int c1, int c2);
};
bool ALGraph::TopologicalSort()
{int k = 0;for (int i = 0; i < vertexNum; i++) //in为0则压栈{if (adjList[i].in == 0){s.push(adjList[i]);}}while (!s.empty()) //循环终止条件:栈为空{vertexNode v = s.top(); //弹栈输出s.pop();result[k++]= v.vertex; //存放拓扑排序结果count++; //计数加一ArcNode* a = v.firstEdge;while (a) //对弹出的结点遍历,所有遍历过的结点的in-1{adjList[a->adjvex].in--;int tmp = adjList[a->adjvex].in;if (tmp == 0) //如果某结点的in变为0,则将其压栈{s.push(adjList[a->adjvex]);}a = a->next;}}if (count < vertexNum) {cout << "false\n";return false;//如果计数小于顶点数则说明有环}else {cout << "true\n";return true;}
}
ALGraph::ALGraph(int v[], int n, int e) //构造函数
{vertexNum = n;arcNum = e;for (int i = 0; i < vertexNum; i++) //顶点初始化{adjList[i].in = 0;adjList[i].vertex = v[i];adjList[i].firstEdge = NULL;result[i] = 0;}ArcNode* s;int vi, vj;char c;for (int i = 0; i < arcNum; i++){s = new ArcNode;cin >> vi >>c>> vj;s->adjvex = vj;s->next = adjList[vi].firstEdge; //头插法adjList[vi].firstEdge = s;adjList[vj].in++; //入度加一}
}
//判断c1,c2的安排是否合理
bool ALGraph::isReasonable(int c1, int c2)
{int p1, p2; //记录c1,c2的下标p1 = result[c1];p2 = result[c2];return p1 < p2 ? true : false; //如果c1的下标小于c2,说明c1安排在c2前面,合理即返回真,否则c1应该安排在c2后面,返回假
}
int main()
{int n, e,c1,c2;bool flag;cin >> n >> e;int v[MAX];for (int i = 0; i < n; i++){v[i] = i;}ALGraph algraph(v, n, e);flag=algraph.TopologicalSort();cin >> c1 >> c2;if (flag){if (algraph.isReasonable(c1, c2))cout << "true" << endl;elsecout << "false\n";}return 0;
}