再写(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就是指到下一个单位时间了。
举个例子
样例输入输出的队列就是:
1 | 2 | 0 | 3 | 5 | 8 | 0 | 4 | 9 | 0 | 6 | 7 | 0 |
拓扑
听完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