算法提高 士兵排队问题

试题
  有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<cstdio>
#include<cstring>
#include<queue>
#include<algorithm>
#define bug(x) printf("%d***\n",x)
#define ls(x) (x<<1)
#define rs(x) (x<<1|1)
using namespace std;
typedef long long ll;

const int maxn=30;
int indegree[maxn]; 
int vis[maxn],mp[30][30];
char ans[maxn];

int cnt;
int head[400];
struct Edge{
	int v,nt;
}edge[400];
void add_edge(int u,int v){
	edge[cnt].nt=head[u];
	edge[cnt].v=v;
	head[u]=cnt++;
}

queue<int> q;
int num;
void topsort(){	
    for(int i=0;i<26;i++){
		if(vis[i]&&!indegree[i]){
			vis[i]=0;
			q.push(i);//不能找到一个点,就直接跳出的话不可以,有可能不是联通图 
		}
	}	
	while(!q.empty()){
		int now=q.front();
		q.pop();
		vis[now]=0;
		ans[num++]=now+'A';
		for(int i=head[now];i!=-1;i=edge[i].nt){
			int v=edge[i].v;
			indegree[v]--;
			if(indegree[v]==0&&vis[v]){
				q.push(v);
			}
		}	
	}
}

char str[10];
int main(){
	cnt=0;
	int n=0;
	memset(head,-1,sizeof(head));
	
	while(gets(str)){
		if(str[0]==EOF) break;
		int a=str[0]-'A',b=str[2]-'A';
		if(!vis[a]){
			vis[a]=1;n++;
		}
		if(!vis[b]){
			vis[b]=1;n++;
		}
		if(str[1]=='>'){//如果重复输入的话,不要再添加 
			indegree[a]++;	
			add_edge(b,a);
		}
		else {
			indegree[b]++;
			add_edge(a,b);
		}	
	}
	num=0;
	topsort();
	if(num<n)
		printf("No Answer!\n");
	else{
		for(int i=n-1;i>=0;i--)
			printf("%c",ans[i]);
		printf("\n");
	}
	return 0;
} 

评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值