拓扑排序-about

再写(shui)一篇博文,拓扑

点击前往---友情链接-AOE

Question(TPS.cpp)

最近有一个工程,有tc个小项目,项目施工方有数量充足的施工队,但是tc个小项目之间有vc个
次序,比如楼房主体就要在地基之后搭建。现已知每个施工队需要相同的一个单位时间完成一个小
项目,施工队主管想要知道每个单位时间施工队该同时干哪几件事,便来请求你的帮助。
Input(TPS.qus)
第一行 是两个数tc和vc,表示小项目数和次序数
第2~vc+1行每行两个整数ft和st,表示ft在st之前发生
Output(cout)
如果输入无误,输出如下
	第一行,是一个整数t,表示完成需要几个单位时间。
	第二行到第t+1行,每行?个整数,表示这个单位时间里要做的事的编号
	这t行一共有tc个整数
否则,输出“Input Wrong!”(无引号)
Test
input:
9 11
1 8
8 9
9 7
1 3
3 4
4 7
2 3
2 4
4 6
2 5
5 6
output:
1 2 
3 5 8 
4 9 
6 7 

这里是分割线


思路

在了解拓扑排序之前,我们需要了解什么是AOV网
AOV网
这个网是一种没有环的有向联通图
每个点(小项目a)表示一件事(XXX施工队完成小项目a)
每条边a->b表示a在b之前发生(a比b先完成)
至于为啥说不能有环,想想,自己发生在自己之前,Impossible,Dui Bu Dui
好,我这里还设了一个队列,表示工程完成的顺序。
0就是指到下一个单位时间了。
举个例子
样例输入输出的队列就是:
1203580490670
拓扑
听完AOV,是不是整个人都轻松了?
其实算法一看代码你秒秒钟就明白了,这里讲几个关键点
Q:为什么要设cv和vis两个vistied数组
A:如果直接set到vis的话,结果就是1 2 3 4 5 6 8 9 7,原因自己模拟,
本题的基本概念是一个单位时间一个单位时间做的,不是一个一个做的。
Q:为什么要设flag?
A:看有没有环吗!

代码{

#ifdef do_self//没直接复制

#include<iostream>
#include<fstream>
#include<queue>
#include<cstring>
#include<cstdlib>
#define ML 1000
using namespace std;
queue<int> LR;
int c=0;//单位时间数量
ifstream fin("TPS.qus");
struct Depend{
	int n,o;
	//n-(n)eed Depend
	//o-Depend (o)n to
};
void TPS(int VC,int RC,Depend RL [ML]){
	//write to pic -- img --
	bool img [ML][ML];
	memset(img,0,sizeof(img));
	for(int i=0;i<RC;i++){
		img[RL[i].o-1][RL[i].n-1]=true;
	//	cout<<RL[i].o<<' '<<RL[i].n<<endl;
	}
	//sort//
	bool vis[ML],cv[ML];
	memset(vis,0,sizeof(vis));
	memset(cv,0,sizeof(cv));
	while(LR.size()-c<VC){
		bool flag=false;
		for(int i=0;i<VC;i++){
			if(!vis[i]){
				bool isok=true;
				for(int j=0;j<VC;j++){
					if(img[j][i]&&!vis[j]){
						isok=false;
						break;
					}
				}
				if(isok){
					flag=true;
					LR.push(i+1);
					cv[i]=true;
				}
			}
		}
		if(!flag){
			cout<<"Input Wrong\n";
			exit(1);
		}else{
			LR.push(0);
			c++;
		}
		memcpy(vis,cv,sizeof(cv));
		//copy 实现 同步 小项目 完成 结果
	}
}
int main(){
	int VC,RC;
	Depend RL [ML];
	fin>>VC>>RC;
	for(int i = 0 ; i < RC ; i++){
		fin>>RL[i].o>>RL[i].n;
	}
	TPS(VC,RC,RL);
	cout<<c<<endl;
	for(;!LR.empty();LR.pop()){
		if(LR.front()!=0)
			cout<<LR.front()<<' ';
		else
			cout<<endl;
	}
	return 0;
}

#endif

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值