首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> C++ >> 關於C++

HDU 1811 判斷有向圖拓撲序唯一性 (UFSet + Tarjan + 拓撲排序)

     編輯:關於C++

問題

給定有向圖關係 (=, <, >),判斷是否存在衝突、不確定或確定唯一拓撲序。多測試用例。

三種狀態輸出

  • CONFLICT:存在矛盾 (如 a
  • UNCERTAIN:無衝突但拓撲序不唯一 (某步有多個入度 0 節點)。
  • OK:無衝突且拓撲序唯一。

解法步驟

  1. 用并查集合併 "=" 關係的節點。
  2. 構建縮點後的 DAG:"<" 邊 u→v,">" 邊 v→u。
  3. Tarjan 求強連通分量,若同一 SCC 內有邊 → CONFLICT。
  4. 對縮點 DAG 拓撲排序 (Kahn 算法),若某步隊列長度 >1 → UNCERTAIN。
  5. 若所有節點入度歸零且無歧義 → OK。

核心代碼結構

// 并查集
int find(int x) { return fa[x]==x ? x : fa[x]=find(fa[x]); }

// Tarjan
void tarjan(int u) {
    dfn[u]=low[u]=++timer;
    st.push(u); inStack[u]=1;
    for (int v : adj[u]) {
        if (!dfn[v]) { tarjan(v); low[u]=min(low[u], low[v]); }
        else if (inStack[v]) low[u]=min(low[u], dfn[v]);
    }
    if (dfn[u]==low[u]) { /* pop SCC */ }
}

// 拓撲排序判斷唯一性
bool topoUnique() {
    queue q;
    for (int i=1; i<=sccCnt; ++i) if (ind[i]==0) q.push(i);
    while (!q.empty()) {
        if (q.size() > 1) return false; // 不唯一
        int u=q.front(); q.pop();
        for (int v: dag[u]) if (--ind[v]==0) q.push(v);
    }
    return true;
}

複雜度

O(n+m) 每測試用例,n≤30000, m≤100000,完全足夠。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved