7-34 任务调度的合理性 (25 分)(思路加详解+兄弟们冲呀)

  • Post author:
  • Post category:其他




一:题目

假定一个工程项目由一组子任务构成,子任务之间有的可以并行执行,有的必须在完成了其它一些子任务后才能执行。“任务调度”包括一组子任务、以及每个子任务可以执行所依赖的子任务集。

比如完成一个专业的所有课程学习和毕业设计可以看成一个本科生要完成的一项工程,各门课程可以看成是子任务。有些课程可以同时开设,比如英语和C程序设计,它们没有必须先修哪门的约束;有些课程则不可以同时开设,因为它们有先后的依赖关系,比如C程序设计和数据结构两门课,必须先学习前者。

但是需要注意的是,对一组子任务,并不是任意的任务调度都是一个可行的方案。比如方案中存在“子任务A依赖于子任务B,子任务B依赖于子任务C,子任务C又依赖于子任务A”,那么这三个任务哪个都不能先执行,这就是一个不可行的方案。你现在的工作是写程序判定任何一个给定的任务调度是否可行。

输入格式:

输入说明:输入第一行给出子任务数N(≤100),子任务按1~N编号。随后N行,每行给出一个子任务的依赖集合:首先给出依赖集合中的子任务数K,随后给出K个子任务编号,整数之间都用空格分隔。

输出格式:

如果方案可行,则输出1,否则输出0。

输入样例1:

12
0
0
2 1 2
0
1 4
1 5
2 3 6
1 3
2 7 8
1 7
1 10
1 7

结尾无空行

输出样例1:

1

结尾无空行

输入样例2:

5
1 4
2 1 4
2 2 5
1 3
0

输出样例2:

0



二:思路分析

这个题把入度直接给你了,省得去求了,即第一列就是按顺序的某个结点的入度,如果有环的话肯定会有结点的入度不会为0;



三:上码

//拓扑排序 如果存在环则不能输出正常序列
#include<stdio.h>
void topology(int N){
   int i,j,k,m,b[105],count=0;
   int Indegree[105]={0};//入度初始化为0 
   int Queue[105],head=0,last=0;
   int c[105][105];//创建二维数组 将有到达这个顶点的 顶点存进去
   for(i = 1; i<=N; i++){
       scanf("%d",&k);
       Indegree[i] = k;//将其入度存进去了
       for(j=0; j<k; j++){
          scanf("%d",&c[i][j]);
        }
   }

   for(i = 1; i<=N; i++){
       if(Indegree[i] == 0)
         Queue[last++]=i;
   }

   while(head - last){
      m = Queue[head++];//出队 将入度为0的出队
      count++;
      //顶点度数开始减一 为0 入队
      for(i=1; i<=N; i++){
          for(j=0; j<105; j++){
              if(c[i][j] == m){
                  Indegree[i]--;
                  if(Indegree[i] == 0)
                    Queue[last++] = i;
              }
          }
      }

   }

   if(count == N ){
       printf("1");
   }
   else
       printf("0");
}
int main(){
    int N;
    scanf("%d",&N);
    topology(N);
}

在这里插入图片描述



四:补充:

如果兄弟们觉得这道题入度给了,自己不用求,觉得不过瘾的话,我这还有码,是求拓扑序列,当然也能判断是否有环和无环

/* 
	1.
		AOV网(Activity On Vertex Network)【顶点——表示活动】
		是一个——有向无回路的图
		顶点——表示活动
		用弧——表示活动间的优先关系的有向图称为-顶点表示活动的网
		即如果a->b,那么a是b的先决条件
		求拓扑序列就是AOV
	2.
		用邻接矩阵存储时 每一列表示这个顶点的入度(有向图中)	
*/
#include<bits/stdc++.h>
using namespace std;

typedef struct GNode* PtrGraph;
typedef struct GNode{
	int Nv;
	int Ne;
	int Date[100][100];
}gnode;

int cnt; //统计每个结点的入度 
vector<int>v;//存入度的 
vector<int>v1;//记录拓扑序列 

//创建图
void creatrGraph(PtrGraph G){
	int N,M;
	cin >> N >> M;
	G->Nv = N;
	G->Ne = M;
	
	//矩阵初始化
	for( int i = 0; i < G->Nv; i++ ){
		for(int j = 0; j < G->Nv; j++ ){
			G->Date[i][j] = 0;
		}
	} 
	 
	//矩阵赋值
	for(int i = 0; i < G->Ne; i++ )
	{
		int a,b;
		cin >> a >> b;
		
		G->Date[a][b] = 1;//有向图	
	} 	
} 
//求取每一列的数据和即为该顶点的入度
void degree(PtrGraph G){
	
	for(int j = 0; j < G->Nv; j++ ){
	
		cnt = 0;
	
		for( int i = 0; i < G->Nv; i++ ){
			if(G->Date[i][j] == 1)
			 cnt++;
		}
	    
	    v.push_back(cnt);
	}
}  
//求拓扑序列

void topology( PtrGraph G ){
	
	queue<int>q;
	int count = 0;//用于计算度数为0的结点的个数 
	
	for( int i = 0; i < G->Nv; i++ )
	{
		if(v[i] == 0)
		q.push(i);//将入度为0的入队		
	} 
		
	//这里就是处理每次去掉一个度数为0的点和其有关系的顶点度数减一 
	while( !q.empty() ){
		
		int temp = q.front();
		q.pop();
		
        v1.push_back(temp); 
		
		count++;
		
		for( int j = 0; j < G->Nv; j++ ){//列 
			
			if( G->Date[temp][j] == 1  ){//在 temp 这一行中 等于 1的 j 需要入度减一 	
				v[j]--;//其入度减一
				
				if( v[j] == 0 ){
				q.push(j);// 将入度为0的入度 
			}
					 	
			}
		}
	} 
	
	if( G->Nv  == count ){//没有环 
		for( int i = 0; i < v1.size(); i++ )
          	cout << v1[i] << ' '; 	
	}else{
		cout << "此图有环"; 
	} 
	
	
} 


int main(){
	
	PtrGraph G = (PtrGraph)malloc(sizeof(struct GNode));
	creatrGraph(G);
	degree(G);
	topology(G);

	
} 


//5 6
//0 1
//0 2
//1 3
//2 1
//2 4
//3 4
//拓扑序列: 0 2 1 3 4

在这里插入图片描述



版权声明:本文为qq_48508278原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。