『洛谷T7835』士兵站隊問題

題目描述

有N名士兵(1<=N<=26),編號依次爲A,B,C,……進行隊列訓練時,指揮官要把一些士兵從高到矮依次排成一行,但現在指揮官不能直接獲得每個士兵的身高信息,只能獲得“P1比P2高”這樣的比較結果(P1,P2∈{A,B,…Z},記爲P1>P2),如“A>B”表示A比B高。

編一程序,根據所得到的比較結果求出符合條件的排隊方案。

注:比較結果中沒有涉及到的士兵不參加排隊。

例如,設有3個士兵,A、B、C,給出關係(A,B),(B,C)。其中(A,B)表示士兵A高於B,當上面的關係給出之後,可以將他們排成一隊:ABC。

輸入輸出格式

輸入格式:
輸入文件中每個比較結果在文件中佔一行。

輸出格式:
若輸入數據無解或不能唯一確定,則輸出“NO ANSWER!”,否則從高到矮依次輸出每一個士兵的編號,中間無分隔符,並把結果寫入文本文件中。

輸入輸出樣例

輸入樣例#1A>B                 
B>F
F>D

這道題目看上去十分的困難,感覺毫無頭緒,但是有經驗的OI選手一眼就可以看出,這是TOP排序啊!(若不知道TOP排序,請見『這裏!』)。但是在簡單的Top排序上又要加入一些判斷,詳情見代碼:

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<math.h>
#include<algorithm>
#include<vector>
#include<queue>
#include<map>
#include<set>
#include<iostream>
using namespace std;
const int Inf=2147483647;
struct node{
    int u,v,w;
}e[100010];
int f[100010];
int b[27],g[27][27],in[27],ans[27];
long long gl(){
    char c=getchar();long long f=1;
    int sum=0;
    while((c>'9' || c<'0') && c!='-')
        c=getchar();
    if(c=='-'){f=-1;c=getchar();}
    while(c>='0' && c<='9'){
        sum=sum*10+c-'0';
        c=getchar();
    }
    return f*sum;
}
int gi(){
    char c=getchar();int f=1,sum=0;
    while((c>'9' || c<'0') && c!='-')
        c=getchar();
    if(c=='-'){f=-1;c=getchar();}
    while(c>='0' && c<='9'){
        sum=sum*10+c-'0';
        c=getchar();
    }
    return f*sum;
}
int find(int x){
    if(f[x]!=x)f[x]=find(f[x]);
    return f[x];
}
void join(int x,int y){
    x=find(x);y=find(y);
    if(x!=y)f[y]=x;
}
void out(int all){
    for(int i=1;i<=all;i++)
        printf("%c",ans[i]+'A'-1);
    puts("");
}
int main(){
    int i,j,k,n,m;
    char c,d,o;
    int all=0;
    while(cin>>c>>o>>d){
        int p=c-'A'+1,q=d-'A'+1;
        g[p][q]=1;in[q]++;
        if(!b[p])all++;//這裏是統計總字母個數
        if(!b[q])all++;
        b[p]=1;b[q]=1;//這裏是爲了後一步
    }
    for(i=1;i<=26;i++)
        if(!b[i])in[i]=Inf;//這裏是表示某一個點爲了不使它進入TOP序列,把他們的初值設爲∞
    n=26;
    i=0;
    do{
        i++;j=1;
        int flag=0;
        while(j<=n && in[j])j++;
        if(j>n)break;
        for(k=j+1;k<=n;k++)
            if(in[k]==0){
                flag=1;break;//這個是爲了判斷答案是否爲1
            }
        if(flag)break;
        ans[i]=j;in[j]=1;
        for(k=1;k<=n;k++)
            if(g[j][k])in[k]--;
    }while(i<all && j<=n);
    if(i<all || j>n)printf("NO ANSWER!\n");
    else out(all);
    return 0;
}

整個代碼簡潔明瞭,一道難題瞬間水過!!!╰(°▽°)╯

發佈了112 篇原創文章 · 獲贊 9 · 訪問量 4萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章