【题目要求】
现在你总共有 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;
else
cout << "false\n";
}
return 0;
}