1. 程式人生 > >【洛谷P1347】排序

【洛谷P1347】排序

題目大意:給定 N 個變數和 M 個變數之間的偏序關係,問能否求出這 N 個變數之間的一個全序。若能,輸出最少利用多少條已知資訊即可求的結果,且輸出該全序;若無解,輸出到第幾條已知資訊可以判定無解;若讀到最後一條資訊也無法判斷,輸出無法判斷。

題解:偏序關係自然對應著一個有向圖,每一個已知資訊等價為給這個有向圖加一條邊,若能夠得到全序,則證明拓撲排序過程中能夠找出一條長度為 N 的鏈,若無解,則是在拓撲排序過程中存在自環,否則就是無法判斷。

程式碼如下

#include <bits/stdc++.h>
using namespace std;
const int maxn=30;

vector<int> G[maxn];
char ops[10];
int n,m,idx,indeg[maxn],tmp[maxn],stk[maxn],top,d[maxn];//d[i]為以 i 結尾的最長路徑
bool circle,certain;

inline void add_edge(int from,int to){G[from].push_back(to),++indeg[to];}

void topo_sort(int now){
    queue<int> q;int dep=1;//dep為當前DAG上的最長路徑的長度
    for(int i=1;i<=n;i++)d[i]=0;
    for(int i=1;i<=n;i++){
        tmp[i]=indeg[i];
        if(!tmp[i])q.push(i),d[i]=1;
    }
    top=0;
    while(q.size()){
        int u=q.front();q.pop();
        stk[++top]=u;
        for(int i=0;i<G[u].size();i++){
            int v=G[u][i];--tmp[v];
            if(!tmp[v])q.push(v);
            d[v]=max(d[v],d[u]+1);
            dep=max(dep,d[v]);
        }
    }
    if(top^n)circle=1,idx=now;
    else if(dep==n)certain=1,idx=now;
}

void solve(){
    for(int i=1;i<=m;i++){
        scanf("%s",ops+1);
        if(circle||certain)break;
        int from=ops[1]-'A'+1,to=ops[3]-'A'+1;
        add_edge(from,to);
        topo_sort(i);
    }
    if(certain){
        printf("Sorted sequence determined after %d relations: ",idx);
        for(int i=1;i<=n;i++)printf("%c",stk[i]+'A'-1);
        printf(".\n");
    }
    else if(circle)printf("Inconsistency found after %d relations.\n",idx);
    else printf("Sorted sequence cannot be determined.\n");
}

int main(){
    scanf("%d%d",&n,&m);
    solve();
    return 0;
}