PAT(甲级)2020年秋季考试 7-4 Professional Ability Test

Posted CSU迦叶

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了PAT(甲级)2020年秋季考试 7-4 Professional Ability Test相关的知识,希望对你有一定的参考价值。

 解题思路:

1.用拓扑排序判断给定的图是否是有向无环图(DAG)

在这个过程当中,对于入度为0的结点,在布尔数组中标记是初始结点

通过入队的结点个数是否等于总个数判断是不是DAG

注意:虽然有队列,但是不需要inq[]数组标记是否入队,当弹出一个元素时,再让计数加一

当一个结点出队,不要把对应的邻接向量清空,不然后面的迪杰斯特拉没法玩orz

2.不是DAG

好办,就分为可以作为起点的结点和不可以的两种情况输出

3.是DAG

加一个超级汇点,让这个汇点连接所有可以作为初始结点的结点,这样就转换成了单源最短路径问题,可以用Dijkstra解决。

但是注意这不是最朴素的Dijkstra

3.1 要记录每个结点的前置结点

然后用深度优先的方式递归输出路径

3.2 拥有第二标尺

完整代码如下(注:考试时没做出来,以下代码仅仅是通过了两个给出的test case)

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<string>
#include<cstring>
#include<vector>
#include<queue>

using namespace std;

const int maxn = 1010;
const int inf = 1000000000;//即10^9 

struct Node{
	int v;//vertex
	int s;//score
	int d;//dollar 
	
	Node(int _v,int _s,int _d):v(_v),s(_s),d(_d){} 
};

vector<Node> Adj[maxn];

int vNum,eNum,qNum,inDegree[maxn] = {0},isStart[maxn] = {0};

bool topologicalSort(){
	queue<int> Q;
	int num = 0;//入队的总结点数 
	
	for(int i=0;i<vNum;i++){
		if(inDegree[i]==0){
			Q.push(i);
			isStart[i] = 1;//i是起始节点 
		}
	}
	while(!Q.empty()){
		int v = Q.front();
		Q.pop();
		for(int i=0;i<Adj[v].size();i++){
			int u = Adj[v][i].v;
			inDegree[u] --;
			if(inDegree[u]==0){
				Q.push(u);
			}
		}
		num ++;
//		Adj[v].clear();		
	}
	
	if(num==vNum)return true;
	else return false;
}

int dis[maxn];
int vou[maxn];

int pre[maxn]; 

void Dijkstra(){
	
	int s = vNum;
	
	bool vis[maxn] = {0};
	
	fill(dis,dis+vNum,inf);
	dis[s] = 0;
	
	fill(vou,vou+vNum,0);
	
	for(int i=0;i<=vNum;i++){//每次点亮一个结点 
		//找当前未点亮结点中距离最近的
		int v = -1,MIN = inf;
		for(int j=0;j<=vNum;j++){//到这一步出现了段错误 
			if(vis[j]==false&&dis[j]<MIN){
				MIN = dis[j];
				v = j;
			}
		}
		
		if(v==-1)return;
		
		vis[v] = true;
		
		for(int j=0;j<Adj[v].size();j++){
			int u = Adj[v][j].v;
			if(dis[u]>dis[v]+Adj[v][j].s&&vis[u]==false){
				dis[u] = dis[v]+Adj[v][j].s;
				vou[u] = vou[v]+Adj[v][j].d;
				pre[u] = v;
			}else if(dis[u]==dis[v]+Adj[v][j].s&&vou[u]<vou[v]+Adj[v][j].d&&vis[u]==false){
				vou[u] = vou[v]+Adj[v][j].d;
				pre[u] = v;
			}
		} 
	} 
	
}

void DFS(int u){//s是起点,u是终点 
	if(u==vNum){
//		printf("%d",u);
		return;
	}
	DFS(pre[u]);
	if(isStart[u]!=1)printf("->");
	printf("%d",u);
}


int main(){
	
	
	scanf("%d %d",&vNum,&eNum);
	
	int v1,v2,s,d;
	
	for(int i=0;i<eNum;i++){
		scanf("%d %d %d %d",&v1,&v2,&s,&d);
		inDegree[v2]++;
		Node node = Node(v2,s,d);
		Adj[v1].push_back(node);
	}
	
	bool tsSuccess = topologicalSort();//拓扑排序成功否
	
	if(tsSuccess){
		//增加一个点,编号为vNum,作为超级源点
		for(int i=0;i<vNum;i++){
			if(isStart[i]==1){
				inDegree[i]++;
				Node node = Node(i,0,0);
				Adj[vNum].push_back(node);
			}
		} 
		
		printf("Okay.\\n");
		Dijkstra();
		scanf("%d",&qNum);
		while(qNum--){
			int u;//destination
			scanf("%d",&u);
			if(isStart[u]==1){
				printf("You may take test %d directly.\\n",u);
			}else{
				DFS(u);
				printf("\\n");
			}	
		}
	}else{
		printf("Impossible.\\n");
		scanf("%d",&qNum);
		while(qNum--){
			int u;
			scanf("%d",&u);
			if(isStart[u]==1)printf("You may take test %d directly.\\n",u);
			else printf("Error.\\n");
		}		
	}
	
	return 0;
}
 

以上是关于PAT(甲级)2020年秋季考试 7-4 Professional Ability Test的主要内容,如果未能解决你的问题,请参考以下文章

PAT(甲级)2019年秋季考试

PAT(甲级)2020年春季考试 7-4 Replacement Selection

PAT(甲级)2021年秋季考试summary

PAT(甲级)2018年秋季考试 7-1 Werewolf - Simple Version

PAT(甲级)2019年秋季考试 7-3 Postfix Expression

PAT(甲级)2019年秋季考试 7-2 Merging Linked Lists