士兵排队问题(拓补排序)(附简要拓补排序思想及算法)

题目描述

有N个士兵(1<=N<=100),编号依次为1,2,...,N.队列训练时,指挥官要把士兵从高到矮排成一行,但指挥官只知道“1 比2 高,7 比 5高”这样的比较结果。
请编写一个程序,对于给出指挥官一些“a比b高”这样信息后,求出一种合理士兵从高到低的排列。
       

输入

输入文件:第一行为数N(N〈=100);表示士兵的个数。以下若干行每行两个数A,B表示A高于B(1<=A,B<=N且A!=B)。

输出

 输出文件:给出一个合法的排队序列,格式如样例。如果没有答案,则输出-1。

 

拓补排序裸题。

首先我们先将讲一讲拓补排序。

拓补排序:

假设我们有一条边x->y

那么y的入度+1;

拓补排序就是对于一个有向无环图

每次找到入度为0的点,删除它并删除所有以他为起点的边

直到整个图为空

则输出顺序为拓补序

而应用的前提就是一道题目中做到一件事需要满足另一件事。而另一件事又需要满足另外一件事。以此类推。。

那么这种题目就很可能用到拓补排序

根据上面的思想我们很容易就能想到如何代码实现。

下面贴代码

#include<iostream> 
#include<cstdio> 
using namespace std; 
int de[101]; 
int que[10001]; 
int head[101]; 
int ans[101],qaq=0; 
struct edge{ 
    int to,next; 
}g[10001]; 
int n,num; 
void ins(int u,int v) 
{ 
    g[++num].next=head[u]; 
    head[u]=num; 
    g[num].to=v; 
} 
void toposort() 
{ 
    int h=1,t=0; 
    for(int i=1;i<=n;i++) 
    { 
        if(de[i]==0) 
        que[++t]=i; 
    } 
    while(h<=t) 
    { 
        int tmp=que[h]; 
        ans[++qaq]=tmp; 
        for(int i=head[tmp];i;i=g[i].next) 
        { 
            if(!--de[g[i].to])que[++t]=g[i].to;      
        } 
        h++; 
    } 
} 
int main(){ 
    scanf("%d",&n); 
    int x,y; 
    while(~scanf("%d%d",&x,&y)) 
    { 
        de[y]++; 
        ins(x,y); 
    } 
    toposort(); 
    if(qaq<n)printf("-1\n"); 
    else 
    { 
        for(int i=1;i<qaq;i++) 
        printf("%d ",ans[i]); 
        printf("%d\n",ans[qaq]); 
    } 
} 

 

posted @ 2017-05-22 16:21  ghostfly233  阅读(1961)  评论(0编辑  收藏  举报