跟这位博友碰到的题目一样:http://blog.youkuaiyun.com/u013088799/article/details/39587403
简单的说就是,几千人要排成一队。有些人要求某些人一定要排在自己前面,某些人一定要排在自己后面。问是否有解,有则给出一个解。
给定的几个预定义结构体、函数原型如下:
typedef struct Request{
string owner; //对某人
bool frontOrBehind; // true 本owner在前applicant申请人之前;;false:本owner在申请人之后
}Request; //
typedef struct Apply{
string applicant; //申请者
list<Request> requests; //
}Apply;
list<string> getValidSeq(list<string>& allMembers,list<Apply>& allApply)
解题思路:判断有向图是否存在回路,显然使用拓扑排序比使用深度(广度)搜索要好些。具体算法是 严蔚敏《数据结构(C语言版)》拓扑排序章节、存储图用 邻接表。
代码如下:
#include<iostream>
#include<cstdio>
#include<string>
#include<list>
#include<hash_map>
#include<cstdlib>
#include<queue>
using namespace std;
#define MAX_VERTEX_NUM (10000)
typedef struct Request{
string owner; //对某人
bool frontOrBehind; // true 本owner在前applicant申请人之前;;false:本owner在申请人之后
Request(string owner,bool frontOrBehind):owner(owner),frontOrBehind(frontOrBehind){}
}Request;
typedef struct Apply{
string applicant; //申请者
list<Request> requests; //
}Apply;
typedef struct ArcNode{
int adjVex;
ArcNode * nextArc;
//该弧信息(或其指针)
ArcNode(){nextArc = NULL;}
}ArcNode;
typedef struct VNode{
//顶点信息(或其指针)
string name;
ArcNode *firstArc;
VNode() {firstArc = NULL;}
}VNode,AdjList[MAX_VERTEX_NUM];
list<string> getValidSeq(list<string>& allMembers,list<Apply>& allApply){
hash_map<string,int> name2id; //哈希容器,快速取得编号
AdjList adjList; //邻接表
int inDegreeOfNodes[MAX_VERTEX_NUM]={0}; //记录每个顶点入度,初始化为0
int numOfAll = allMembers.size();
list<string>::iterator iter_mem = allMembers.begin();
for(int i=0;iter_mem != allMembers.end();iter_mem++,i++){
name2id[*iter_mem] = i;
(adjList[i]).name = *iter_mem;
}
list<Apply>::iterator iter_apply = allApply.begin();
list<Request>::iterator iter_req;
for(int i=0;iter_apply != allApply.end();iter_apply++){
int idOfApplier = name2id[iter_apply->applicant];
list<Request>::iterator iter_req = iter_apply->requests.begin();
for( ;iter_req != iter_apply->requests.end();iter_req++){
int idOfRef = name2id[iter_req->owner];
int id_front,id_behind;
if(iter_req->frontOrBehind){
id_front = idOfRef;
id_behind = idOfApplier;
}
else{
id_front = idOfApplier;
id_behind = idOfRef;
}
ArcNode * ptr = adjList[id_front].firstArc;
while(ptr && ptr->nextArc)
ptr = ptr->nextArc;
ArcNode * newArc = (ArcNode*)malloc(sizeof(ArcNode));
newArc->adjVex = id_behind;
newArc->nextArc = NULL;
if(!ptr)
adjList[id_front].firstArc = newArc;
else
ptr->nextArc = newArc;
inDegreeOfNodes[id_behind]++; //统计入度
}
}
queue<int> degZeroNodes;
list<string> result;
int cnt = 0;
for(int i=0;i<numOfAll;i++){
if(!inDegreeOfNodes[i])
degZeroNodes.push(i);
}
while(!degZeroNodes.empty()){
int curId = degZeroNodes.front();
result.push_back(adjList[curId].name);
degZeroNodes.pop();
ArcNode *ptr = adjList[curId].firstArc;
while(ptr){
int id = ptr->adjVex;
inDegreeOfNodes[id]--;
if(! inDegreeOfNodes[id])
degZeroNodes.push(id);
ptr = ptr->nextArc;
}
cnt++;
}
//free
for(int i=0;i<numOfAll;i++){
ArcNode *ptr = adjList[i].firstArc,*next;
while(ptr){
next = ptr->nextArc;
free(ptr);
ptr = next;
}
}
if(cnt<numOfAll){ //NULL 不存在合法解
result.clear();
return result;
}
return result;
}
/*
* 制定输入信息格式为:
* 总共人数(n)
* n 个人人名
* 提出申请的人数
* 申请人姓名 放在自己前面的人数 后面的人数 放在自己前面的人名 放在自己后面的人名
*/
int main(){
list<string> members;
list<Apply> applies;
list<string> result;
freopen("input.txt","r",stdin);
int numOfMem,numOfApply;
while(cin>>numOfMem){
members.clear();
applies.clear();
result.clear();
for(int i=0;i<numOfMem;i++){
string name;
cin>>name;
members.push_back(name);
}
cin>>numOfApply;
for(int i=0;i<numOfApply;i++){
string applier;
int numFront,numBehind;
cin>>applier>>numFront>>numBehind;
Apply myApply;
myApply.applicant = applier;
for(int j=0;j<numFront;j++){
string name;
cin>>name;
myApply.requests.push_back(Request(name,true));
}
for(int k=0;k<numBehind;k++){
string name;
cin>>name;
myApply.requests.push_back(Request(name,false));
}
applies.push_back(myApply);
}
result = getValidSeq(members,applies);
if(result.empty())
cout<<"NO SOLUTION!!!"<<endl;
else{
for(list<string>::iterator iter_result = result.begin();iter_result!=result.end();iter_result++)
cout<<*iter_result<<" ";
cout<<endl;
}
}
}
测试用例如下:
10
a b c d e f g h i j
2
b 2 2 e f i j
c 2 2 g h a b
10
a b c d e f g h i j
3
b 2 2 e f i j
c 2 2 g h a b
g 1 1 i a
测试用例得到结果如下:
d e f g h c a b i j
NO SOLUTION!!!