算法提高 士兵排队问题

试题
  有N个士兵(1≤N≤26),编号依次为A,B,C,…,队列训练时,指挥官要把一些士兵从高到矮一次排成一行,但现在指挥官不能直接获得每个人的身高信息,只能获得“P1比P2高”这样的比较结果(P1、P2∈A,B,C,…,Z,记为 P1>P2),如”A>B”表示A比B高。
  请编一程序,根据所得到的比较结果求出一种符合条件的排队方案。
  (注:比较结果中没有涉及的士兵不参加排队)
输入要求
  比较结果从文本文件中读入(文件由键盘输入),每个比较结果在文本文件中占一行。
输出要求
  若输入数据无解,打印“No Answer!”信息,否则从高到矮一次输出每一个士兵的编号,中间无分割符,并把结果写入文本文件中,文件由键盘输入:
样例输入
A>B
B>D
F>D
样例输出
AFBD



问题:拓扑排序,将所有士兵之间的关系从大到小连一条边(或者相反,但是要全部按照同一个方向)


#include<stdio.h>
#include<math.h>
#include<iostream>
#include<string>
#include<vector>
#include<queue>
#include<string.h>
#include<algorithm>
using namespace std;

const int maxn = 30;
vector<int>d[maxn],x; 		//v[i][j]表示i>j,即i->j这一条有向边,x[i]表示有的点 
int in[maxn];				//in[i]表示i点的入边条数 
int vis[maxn];
int ans[maxn];
//拓扑排序 
void top_sort()
{
	queue<int>Q;
	int cnt = 0;
	
	for(int i = 0; i < x.size(); i++){
		if (vis[x[i]] == 0 && in[x[i]] == 0){ 	//如果入边为0并且没有访问过,那么就可以是起始点,vis防止重复加入 
			vis[x[i]] = 1;
			Q.push(x[i]);
		}
	}
	
	while(!Q.empty()){
		int t = Q.front();	//t为没有入边的点 
		Q.pop();
		//加入该点
		ans[cnt++] = t;
		 
		for(int i = 0; i < d[t].size(); i++){
			int v= d[t][i];	//指向的终点 
			in[v]--;
			if (in[v] == 0)	//没有入边 
				Q.push(v);
		}
	}
	
	if (cnt)
	for(int i = 0; i < cnt; i++){
		printf("%c",ans[i]+'A');
	}
	else	
		cout << "No Answer!" << endl;
}

int main()
{	
	char s[5];
	
	memset(in,0,sizeof(in)); 
	memset(vis,0,sizeof(vis));
	while(~scanf("%s",s)){
		int u = s[0]-'A';
		int v = s[2]-'A';
		x.push_back(u);
		x.push_back(v);
		if(s[1] == '>'){
			d[u].push_back(v);
			in[v]++; 
		}
		else{
			d[v].push_back(u);
			in[u]++;
		}
	}
	top_sort();	
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值